Housekeep (dependencies and other improvements)#132
Housekeep (dependencies and other improvements)#132matejsemancik wants to merge 27 commits intodevelopfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds ProjectSettings.Android.BuildTypes.all and IOS.IsStaticFrameworkProperty. Extends the annotations-processor plugin with properties useKoin, useComponentFactory, and androidBuildTypes and adds manual wiring to derive KSP variant task names from androidBuildTypes with mustRunAfter ordering against kspCommonMainKotlinMetadata. Sets androidBuildTypes = ProjectSettings.Android.BuildTypes.all in many shared modules. Removes iosX64 from multiple KMP targets. Introduces KMP static/dynamic control (KMP_IS_STATIC) across xcconfigs, Makefile, and shared Gradle iOS framework binaries. Adds Compose Showcase component, preview helpers/noOpActions for screens, README updates, gradle.properties and version catalog bumps, and deletes iOS UI tests. Sequence Diagram(s)mermaid ProjectBuild->>AnnotationsExt: set androidBuildTypes = ProjectSettings.Android.BuildTypes.all Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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 Tip You can customize the tone of the review comments and chat replies.Configure the |
This commit adds support for build variant-aware KSP (Kotlin Symbol Processing) tasks. Key changes: - Adds a mechanism to the `conventions-annotations-processor` to correctly wire KSP task dependencies for different Android build types (e.g., debug, release). - Updates all relevant `build.gradle.kts` files to pass the build types to the convention plugin. - Bumps the `ksp` version to `2.3.0`.
| arg("KOIN_CONFIG_CHECK", "true") | ||
| arg("KOIN_CONFIG_CHECK", "false") |
There was a problem hiding this comment.
I'm disabling this for now because Koin annotations somehow refuses to detect dependencies with named qualifier from the same subproject.
Generated by 🚫 Danger |
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
buildSrc/src/main/kotlin/app/futured/kmptemplate/gradle/configuration/ProjectSettings.kt(1 hunks)convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts(4 hunks)gradle.properties(1 hunks)gradle/libs.versions.toml(3 hunks)shared/app/build.gradle.kts(1 hunks)shared/feature/build.gradle.kts(1 hunks)shared/network/graphql/build.gradle.kts(1 hunks)shared/persistence/build.gradle.kts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{kt,kts}
📄 CodeRabbit inference engine (CLAUDE.md)
Max line length: 140 characters
Files:
shared/feature/build.gradle.ktsshared/persistence/build.gradle.ktsbuildSrc/src/main/kotlin/app/futured/kmptemplate/gradle/configuration/ProjectSettings.ktshared/app/build.gradle.ktsshared/network/graphql/build.gradle.ktsconvention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts
**/*.kt
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.kt: Error handling: Use sealed NetworkError classes and model operations as results (Success/Failure)
Max 25 functions per class
Max 20 functions per file
Files:
buildSrc/src/main/kotlin/app/futured/kmptemplate/gradle/configuration/ProjectSettings.kt
🧠 Learnings (1)
📚 Learning: 2025-09-03T08:24:27.077Z
Learnt from: CR
Repo: futuredapp/kmp-futured-template PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-03T08:24:27.077Z
Learning: Applies to **/*.{android.kt,ios.kt} : Platform-specific code: Place implementations in files suffixed with .android.kt and .ios.kt
Applied to files:
shared/feature/build.gradle.ktsshared/persistence/build.gradle.ktsshared/app/build.gradle.ktsgradle/libs.versions.tomlshared/network/graphql/build.gradle.ktsconvention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts
🔇 Additional comments (9)
gradle.properties (1)
3-3: LGTM: Clean separation of Kotlin daemon JVM options.The new
kotlin.daemon.jvm.optionsproperty properly separates Kotlin-specific JVM settings, and the 1g metaspace allocation aligns with the updated Kotlin 2.2.10 toolchain.shared/app/build.gradle.kts (1)
25-25: LGTM: Consistent build type configuration.The addition of
androidBuildTypes = ProjectSettings.Android.BuildTypes.allproperly enables all Android build types (Debug, Enterprise, Release) for Koin annotation processing in this module, aligning with the new centralized build type configuration.shared/persistence/build.gradle.kts (1)
15-15: LGTM: Consistent build type configuration.The build type configuration matches the pattern established in other modules, properly enabling all Android build types for annotation processing.
shared/network/graphql/build.gradle.kts (1)
18-18: LGTM: Consistent build type configuration.The build type configuration properly enables all Android build types for this module's annotation processing, maintaining consistency across the codebase.
shared/feature/build.gradle.kts (1)
17-17: LGTM: Consistent build type configuration.The build type configuration is properly applied alongside the existing
useKoinanduseComponentFactorysettings, enabling comprehensive annotation processing for all build variants.buildSrc/src/main/kotlin/app/futured/kmptemplate/gradle/configuration/ProjectSettings.kt (1)
30-30: LGTM: Clean aggregation of build type constants.The
allproperty provides a convenient single source of truth for iterating over all build types, eliminating duplication across module configurations.convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts (3)
13-26: LGTM: Well-documented extension properties.The new configuration properties are clearly documented and provide a clean API for configuring annotation processing behavior across modules.
36-36: LGTM: KOIN_CONFIG_CHECK disabled as intended.Setting
KOIN_CONFIG_CHECKtofalsealigns with the past review comment indicating that Koin annotations has issues detecting dependencies with named qualifiers. This is a deliberate configuration choice.
76-82: Task naming convention is correct—no issues found.KSP creates task names like kspDebugKotlinAndroid and kspReleaseKotlinAndroid for Android build variants, which matches the pattern used in the code:
"ksp${it.uppercaseFirstChar()}KotlinAndroid". ThemustRunAfterconstraint will work as intended; the named tasks will be found and the dependency will be properly wired.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
gradle.properties(1 hunks)gradle/libs.versions.toml(3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-03T08:24:27.077Z
Learnt from: CR
Repo: futuredapp/kmp-futured-template PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-03T08:24:27.077Z
Learning: Applies to **/*.{android.kt,ios.kt} : Platform-specific code: Place implementations in files suffixed with .android.kt and .ios.kt
Applied to files:
gradle/libs.versions.toml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: check-android / Lint & Tests
- GitHub Check: check-ios / Test
🔇 Additional comments (2)
gradle.properties (1)
2-3: Good fix: syntax error corrected and Kotlin daemon options properly separated.The previous syntax error (trailing quote) has been resolved, and the kotlin.daemon.jvm.options are now correctly isolated from org.gradle.jvmargs, which is a cleaner configuration approach.
gradle/libs.versions.toml (1)
22-23: Verify Ktorfit 2.6.5 compatibility with Ktor 3.3.3.The previous review identified that Ktorfit 2.6.4's Ktor version is 3.2.1. The patch-level bump to Ktorfit 2.6.5 may not add support for Ktor 3.3.3 (a minor version ahead). Please verify this pairing is supported, either by testing the build or checking Ktorfit 2.6.5 release notes.
gradle/libs.versions.toml
Outdated
| ksp = "2.1.20-1.0.32" # Must be compatible with: `kotlin` | ||
| agp = "8.13.1" | ||
| kotlin = "2.2.20" | ||
| ksp = "2.3.0" |
There was a problem hiding this comment.
CRITICAL: KSP version does not meet Koin Annotations 2.3.1 requirement.
Koin Annotations 2.3.1 requires KSP 2.3.2, but Line 4 specifies KSP 2.3.0. This version mismatch will cause compilation failures.
Update Line 4 to match the requirement:
- ksp = "2.3.0"
+ ksp = "2.3.2"Also applies to: 13-13
🤖 Prompt for AI Agents
In gradle/libs.versions.toml around lines 4 and 13, the KSP version is pinned to
2.3.0 which is incompatible with Koin Annotations 2.3.1; update the ksp entries
on those lines to 2.3.2 so they match Koin's requirement (ensure both
occurrences are changed and any related dependency entries remain consistent).
|
Koin Annotations |
Generated by 🚫 Danger |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Enable iOS preview + screen preview example
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (6)
shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginScreen.kt (1)
13-15: Nit: add explicit): Actionsreturn type for consistency.All other
noOpActions()factories in the codebase (FirstScreen,PickerScreen,TEMPLATEScreen) explicitly annotate the return type as: Actions. Inferring it here is valid but inconsistent.♻️ Proposed fix
- fun noOpActions() = object : Actions { + fun noOpActions(): Actions = object : Actions {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginScreen.kt` around lines 13 - 15, Add an explicit return type to the noOpActions factory to match other factories: change the function declaration for noOpActions in LoginScreen (the function that returns an object : Actions and currently defined as fun noOpActions() = ... ) to explicitly declare the return type as : Actions (i.e., fun noOpActions(): Actions = ...), keeping the same body and object implementation.androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/FirstScreenUi.kt (1)
112-119: RedundantSurfaceinsideShowcase— inconsistent with other previews.
Showcasealready wraps content in aSurface(color = MaterialTheme.colorScheme.background). Adding another bareSurface {}inside (which defaults tocolorScheme.surface) is inconsistent with_TemplateScreenUi.ktandPickerScreenUi.kt, which both useShowcase { Content(...) }directly. The innerSurfacealso has no effect sinceContentrenders aScaffoldthat owns its own background.♻️ Proposed fix
private fun FirstScreenPreview() = Showcase { - Surface { - Content( - viewState = FirstScreenPreviews.viewState(), - actions = noOpActions(), - modifier = Modifier.fillMaxSize(), - ) - } + Content( + viewState = FirstScreenPreviews.viewState(), + actions = noOpActions(), + modifier = Modifier.fillMaxSize(), + ) }Also remove the now-unused import:
-import androidx.compose.material3.Surface🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/FirstScreenUi.kt` around lines 112 - 119, Remove the redundant inner Surface from the FirstScreenPreview function: instead of wrapping Content in Surface(), call Showcase { Content(...) } directly (update the FirstScreenPreview function that currently calls Showcase { Surface { Content(viewState = FirstScreenPreviews.viewState(), actions = noOpActions(), modifier = Modifier.fillMaxSize()) } } ). Also remove the now-unused Surface import that becomes dead after this change so imports match other previews like _TemplateScreenUi.kt and PickerScreenUi.kt.androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/components/Showcase.kt (1)
12-19: Consider movingShowcaseto a debug source set.
Showcaseis only ever called from@Preview-annotated private functions, which are stripped from release builds. The composable itself, however, is compiled into the production APK. Moving it toandroidApp/src/debug/kotlin/…would keep it out of release builds and signal its preview-only intent.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/components/Showcase.kt` around lines 12 - 19, The Showcase composable (function Showcase, referencing MyApplicationTheme and Surface) is preview-only but currently compiled into production; move the Showcase declaration into the debug source set under the same package so it is only included in debug/preview builds, update any imports if needed, and ensure any `@Preview` callers remain in debug or reference the new debug-only Showcase; keep the function signature and behavior unchanged.androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/LoginScreenUi.kt (1)
57-62: RedundantSurfaceinsideShowcase
Showcasealready provides aSurfacewithcolor = MaterialTheme.colorScheme.background(seeandroidApp/.../ui/components/Showcase.ktlines 13–15). The extraSurface { }here is a no-op wrapper.♻️ Proposed fix
`@Preview` `@Composable` private fun LoginScreenPreview() = Showcase { - Surface { - Content( - actions = noOpActions(), - modifier = Modifier.fillMaxSize(), - ) - } + Content( + actions = noOpActions(), + modifier = Modifier.fillMaxSize(), + ) }Also remove the now-unused import:
-import androidx.compose.material3.Surface🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/LoginScreenUi.kt` around lines 57 - 62, Remove the redundant Surface wrapper inside the Showcase usage: delete the outer Surface { ... } so that Content(...) is passed directly to Showcase (keeping actions = noOpActions() and modifier = Modifier.fillMaxSize()); then remove the now-unused Surface import from LoginScreenUi.kt. Locate the Showcase usage in LoginScreenUi (where Content is currently wrapped) and update it to call Content directly, and remove any unused androidx.compose.material3.Surface import.iosApp/shared/KMP/Makefile (2)
26-33:checkmakemaxbodylengthwarning:buildtarget body is 7 lines (limit: 5).The four
@echodiagnostics cause this. They can be consolidated into a single@printfcall or extracted into adefinemacro to bring the body under the configured limit.♻️ Example using `printf` to consolidate echoes
build: - `@echo` "------------------------------------------------" - `@echo` "Config: $(KMP_FRAMEWORK_BUILD_TYPE) | Flavor: $(KMP_BUILD_FLAVOR)" - `@echo` "Static: $(KMP_IS_STATIC)" - `@echo` "Executing: ./gradlew $(GRADLE_TASK) $(GRADLE_ARGS)" - `@echo` "------------------------------------------------" + `@printf` -- "------------------------------------------------\nConfig: %s | Flavor: %s\nStatic: %s\nExecuting: ./gradlew %s %s\n------------------------------------------------\n" \ + "$(KMP_FRAMEWORK_BUILD_TYPE)" "$(KMP_BUILD_FLAVOR)" "$(KMP_IS_STATIC)" "$(GRADLE_TASK)" "$(GRADLE_ARGS)" cd ../../.. && \ ./gradlew $(GRADLE_TASK) --no-daemon $(GRADLE_ARGS)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@iosApp/shared/KMP/Makefile` around lines 26 - 33, The build target in the Makefile has too many lines due to four separate `@echo` calls; replace them with a single consolidated output (e.g., one `@printf` that prints the same header, config, flavor, static flag, and executing line) or extract them into a Makefile define/variable and call it once, keeping the rest of the target (cd ../../.. && ./gradlew $(GRADLE_TASK) --no-daemon $(GRADLE_ARGS)) unchanged; update references to the same variables (KMP_FRAMEWORK_BUILD_TYPE, KMP_BUILD_FLAVOR, KMP_IS_STATIC, GRADLE_TASK, GRADLE_ARGS) so the printed message remains identical.
13-14: Consider adding aKMP_BUILD_FLAVORguard for consistency.
KMP_FRAMEWORK_BUILD_TYPEis validated with$(error ...)(line 7), butKMP_BUILD_FLAVORis used without any guard. If unset, Gradle receives-Pbuildkonfig.flavor=with an empty value, which likely produces a confusing downstream failure.♻️ Proposed guard (after the existing BUILD_MODE block)
endif + +# Validate flavor +ifndef KMP_BUILD_FLAVOR + $(error KMP_BUILD_FLAVOR is not set) +endif + # Task name: assembleAndCopy[Debug|Release]SwiftPackage🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@iosApp/shared/KMP/Makefile` around lines 13 - 14, Add a guard to fail fast when KMP_BUILD_FLAVOR is not set: check the KMP_BUILD_FLAVOR variable (similar to the existing KMP_FRAMEWORK_BUILD_TYPE validation) and invoke $(error ...) with a clear message if it is empty, then safely construct GRADLE_ARGS := -Pbuildkonfig.flavor=$(KMP_BUILD_FLAVOR); place this check after the BUILD_MODE block so the Makefile will not pass an empty -Pbuildkonfig.flavor to Gradle.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/_TemplateScreenUi.kt`:
- Around line 6-7: Replace usage of collectAsState with lifecycle-aware
collectAsStateWithLifecycle: change the import from
androidx.compose.runtime.collectAsState to
androidx.lifecycle.compose.collectAsStateWithLifecycle and update any calls in
the TemplateScreenUi (e.g., where viewModel.someFlow is collected with
collectAsState) to use collectAsStateWithLifecycle() instead while keeping the
existing by delegation/getValue usage (getValue) unchanged; ensure all
occurrences (including the one flagged and the similar occurrence at line 29)
are updated so the Flow respects Android lifecycle.
In `@gradle.properties`:
- Around line 2-3: The property key on line 3 is wrong: replace
kotlin.daemon.jvm.options with kotlin.daemon.jvmargs so the Kotlin daemon JVM
arguments are set correctly; update the entry to use
kotlin.daemon.jvmargs=-XX:MaxMetaspaceSize=1g and leave org.gradle.jvmargs
unchanged.
- Line 3: Replace the incorrect gradle.properties key kotlin.daemon.jvm.options
with the correct property kotlin.daemon.jvmargs so the Kotlin Gradle Plugin
applies the JVM argument; update the entry to use kotlin.daemon.jvmargs and keep
the value -XX:MaxMetaspaceSize=1g (ensuring any existing org.gradle.jvmargs
usage isn't duplicated) so the Kotlin daemon receives the MaxMetaspaceSize
setting.
In `@shared/app/build.gradle.kts`:
- Around line 46-49: The iOS target list now only includes iosArm64() and
iosSimulatorArm64(), which removes iosX64() and thus drops Intel Mac simulator
support; add a clear note explaining that iOS development requires an Apple
Silicon Mac (and that iosX64 was intentionally omitted) so contributors know the
requirement. Update the documentation (either add a short comment above the list
that contains iosArm64() and iosSimulatorArm64() in build.gradle.kts and/or add
a line in the repo README) stating the Apple Silicon requirement, the rationale,
and any CI note about self-hosted Apple Silicon runners to guide contributors.
---
Nitpick comments:
In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/components/Showcase.kt`:
- Around line 12-19: The Showcase composable (function Showcase, referencing
MyApplicationTheme and Surface) is preview-only but currently compiled into
production; move the Showcase declaration into the debug source set under the
same package so it is only included in debug/preview builds, update any imports
if needed, and ensure any `@Preview` callers remain in debug or reference the new
debug-only Showcase; keep the function signature and behavior unchanged.
In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/FirstScreenUi.kt`:
- Around line 112-119: Remove the redundant inner Surface from the
FirstScreenPreview function: instead of wrapping Content in Surface(), call
Showcase { Content(...) } directly (update the FirstScreenPreview function that
currently calls Showcase { Surface { Content(viewState =
FirstScreenPreviews.viewState(), actions = noOpActions(), modifier =
Modifier.fillMaxSize()) } } ). Also remove the now-unused Surface import that
becomes dead after this change so imports match other previews like
_TemplateScreenUi.kt and PickerScreenUi.kt.
In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/LoginScreenUi.kt`:
- Around line 57-62: Remove the redundant Surface wrapper inside the Showcase
usage: delete the outer Surface { ... } so that Content(...) is passed directly
to Showcase (keeping actions = noOpActions() and modifier =
Modifier.fillMaxSize()); then remove the now-unused Surface import from
LoginScreenUi.kt. Locate the Showcase usage in LoginScreenUi (where Content is
currently wrapped) and update it to call Content directly, and remove any unused
androidx.compose.material3.Surface import.
In `@iosApp/shared/KMP/Makefile`:
- Around line 26-33: The build target in the Makefile has too many lines due to
four separate `@echo` calls; replace them with a single consolidated output (e.g.,
one `@printf` that prints the same header, config, flavor, static flag, and
executing line) or extract them into a Makefile define/variable and call it
once, keeping the rest of the target (cd ../../.. && ./gradlew $(GRADLE_TASK)
--no-daemon $(GRADLE_ARGS)) unchanged; update references to the same variables
(KMP_FRAMEWORK_BUILD_TYPE, KMP_BUILD_FLAVOR, KMP_IS_STATIC, GRADLE_TASK,
GRADLE_ARGS) so the printed message remains identical.
- Around line 13-14: Add a guard to fail fast when KMP_BUILD_FLAVOR is not set:
check the KMP_BUILD_FLAVOR variable (similar to the existing
KMP_FRAMEWORK_BUILD_TYPE validation) and invoke $(error ...) with a clear
message if it is empty, then safely construct GRADLE_ARGS :=
-Pbuildkonfig.flavor=$(KMP_BUILD_FLAVOR); place this check after the BUILD_MODE
block so the Makefile will not pass an empty -Pbuildkonfig.flavor to Gradle.
In
`@shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginScreen.kt`:
- Around line 13-15: Add an explicit return type to the noOpActions factory to
match other factories: change the function declaration for noOpActions in
LoginScreen (the function that returns an object : Actions and currently defined
as fun noOpActions() = ... ) to explicitly declare the return type as : Actions
(i.e., fun noOpActions(): Actions = ...), keeping the same body and object
implementation.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
README.mdandroidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/components/Showcase.ktandroidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/FirstScreenUi.ktandroidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/LoginScreenUi.ktandroidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/PickerScreenUi.ktandroidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/_TemplateScreenUi.ktbuildSrc/src/main/kotlin/app/futured/kmptemplate/gradle/configuration/ProjectSettings.ktgradle.propertiesiosApp/Config Files/Beta.xcconfigiosApp/Config Files/Debug.xcconfigiosApp/Config Files/Release.xcconfigiosApp/iosApp/Views/Screen/First/FirstView.swiftiosApp/shared/KMP/Makefileshared/app/build.gradle.ktsshared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/_template/_TemplateScreen.ktshared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/firstScreen/FirstScreen.ktshared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/firstScreen/FirstScreenPreviews.ktshared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginScreen.ktshared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/picker/PickerScreen.kt
✅ Files skipped from review due to trivial changes (2)
- README.md
- iosApp/Config Files/Beta.xcconfig
| import androidx.compose.runtime.collectAsState | ||
| import androidx.compose.runtime.getValue |
There was a problem hiding this comment.
Template uses collectAsState() — replace with collectAsStateWithLifecycle().
collectAsState() collects unconditionally, ignoring the Android lifecycle. When developers copy this template they will inherit a flow that keeps running (and potentially triggers recompositions) even while the screen is backgrounded/stopped. Every other screen in the project already uses collectAsStateWithLifecycle() from androidx.lifecycle.compose.
🐛 Proposed fix
-import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.getValue
+import androidx.compose.runtime.getValue
+import androidx.lifecycle.compose.collectAsStateWithLifecycle- val viewState by screen.viewState.collectAsState()
+ val viewState by screen.viewState.collectAsStateWithLifecycle()Also applies to: 29-29
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/_TemplateScreenUi.kt`
around lines 6 - 7, Replace usage of collectAsState with lifecycle-aware
collectAsStateWithLifecycle: change the import from
androidx.compose.runtime.collectAsState to
androidx.lifecycle.compose.collectAsStateWithLifecycle and update any calls in
the TemplateScreenUi (e.g., where viewModel.someFlow is collected with
collectAsState) to use collectAsStateWithLifecycle() instead while keeping the
existing by delegation/getValue usage (getValue) unchanged; ensure all
occurrences (including the one flagged and the similar occurrence at line 29)
are updated so the Flow respects Android lifecycle.
| org.gradle.jvmargs=-Xmx6g -Xms256m -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError | ||
| kotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
kotlin.daemon.jvm.options Kotlin Gradle Plugin correct property configuration
💡 Result:
To set Kotlin daemon JVM options with the Kotlin Gradle Plugin, you have two different knobs (they behave differently):
1) kotlin.daemon.jvm.options (this is a system property)
You don’t put kotlin.daemon.jvm.options=... directly in gradle.properties. Instead, you pass it as a -D... inside org.gradle.jvmargs, and the value must be comma-separated with no spaces:
# gradle.properties
org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m,Xms500mRules/quirks:
- Use commas, no spaces (anything after a space is treated as Gradle’s JVM args, not Kotlin’s).
- The leading
-is only used for certain args (per Kotlin docs). - On Gradle 7.0–7.1.1 with JDK 9+ (Kotlin DSL script compilation), this can be ignored; Kotlin recommends upgrading Gradle or using
kotlin.daemon.jvmargsinstead. [1]
2) kotlin.daemon.jvmargs (this is a Gradle property, usually the preferred approach)
Set it directly in gradle.properties as a normal space-separated JVM arg list:
# gradle.properties
kotlin.daemon.jvmargs=-Xmx1500m -Xms500mKotlin notes that if you don’t set -XX:ReservedCodeCacheSize, KGP applies a default (320m). [1]
Precedence (important if you set more than one)
Kotlin daemon JVM args are applied in an override order; kotlin.daemon.jvmargs overrides kotlin.daemon.jvm.options (and both can be overridden again via the kotlin { kotlinDaemonJvmArgs = ... } DSL or per-task config). [1]
Source: Kotlin docs (“Setting Kotlin daemon’s JVM arguments”). [1]
Use kotlin.daemon.jvmargs instead of kotlin.daemon.jvm.options on line 3.
Line 3 incorrectly uses kotlin.daemon.jvm.options as a gradle.properties entry. According to the Kotlin Gradle Plugin documentation, kotlin.daemon.jvm.options is a system property intended to be passed as -Dkotlin.daemon.jvm.options=... within org.gradle.jvmargs, not set directly in gradle.properties. The correct gradle.properties property for configuring Kotlin daemon JVM arguments is kotlin.daemon.jvmargs. Change line 3 to:
kotlin.daemon.jvmargs=-XX:MaxMetaspaceSize=1g
Lines 2 and 26 are correct.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@gradle.properties` around lines 2 - 3, The property key on line 3 is wrong:
replace kotlin.daemon.jvm.options with kotlin.daemon.jvmargs so the Kotlin
daemon JVM arguments are set correctly; update the entry to use
kotlin.daemon.jvmargs=-XX:MaxMetaspaceSize=1g and leave org.gradle.jvmargs
unchanged.
| #Gradle | ||
| org.gradle.jvmargs=-Xmx6g -Xms256m -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dkotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g | ||
| org.gradle.jvmargs=-Xmx6g -Xms256m -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError | ||
| kotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Check if gradle.properties exists and read its contents
find . -name "gradle.properties" -type fRepository: futuredapp/kmp-futured-template
Length of output: 94
🌐 Web query:
Kotlin Gradle Plugin kotlin.daemon.jvmargs property gradle.properties
💡 Result:
To set Kotlin compiler daemon JVM arguments for the Kotlin Gradle Plugin (KGP) via gradle.properties, add:
# gradle.properties
kotlin.daemon.jvmargs=-Xmx1500m -Xms500mNotes:
- This is a Gradle property specifically read by KGP to configure the Kotlin daemon JVM. (kotlinlang.org)
- If you don’t set
-XX:ReservedCodeCacheSize, KGP applies a default of 320m. (kotlinlang.org) - There’s also an alternative that routes through
org.gradle.jvmargsas a system property (comma-separated, no spaces), which is applied beforekotlin.daemon.jvmargsin the override order: (kotlinlang.org)
org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m,-Xms500mCitations:
- 1: https://kotlinlang.org/docs/gradle-compilation-and-caches.html?utm_source=openai
- 2: https://kotlinlang.org/docs/gradle-compilation-and-caches.html?utm_source=openai
- 3: https://kotlinlang.org/docs/gradle-compilation-and-caches.html?utm_source=openai
🌐 Web query:
kotlin.daemon.jvm.options vs kotlin.daemon.jvmargs Kotlin Gradle Plugin
💡 Result:
Both settings configure the Kotlin compiler daemon’s JVM arguments (not the Gradle daemon’s), but they enter the build in different ways and use different syntax/precedence.
kotlin.daemon.jvm.options
- What it is: a JVM system property that you pass to the Gradle daemon JVM, typically via
org.gradle.jvmargs. - How to set:
org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m,Xms500m
- Syntax quirks: values are comma-separated with no spaces, and
-is only allowed before some options (likeXmx,XX:MaxMetaspaceSize,XX:ReservedCodeCacheSize). - Known edge case: can be ignored in certain Gradle 7.0–7.1.1 + JDK9+ + Kotlin DSL compilation scenarios; Kotlin docs suggest using
kotlin.daemon.jvmargs(or upgrading Gradle) to avoid this. [1]
kotlin.daemon.jvmargs
- What it is: a Gradle property read by the Kotlin Gradle plugin.
- How to set:
kotlin.daemon.jvmargs=-Xmx1500m -Xms500m - Syntax: normal JVM-arg format (space-separated).
- Recommendation: generally the simpler/more reliable way to set Kotlin daemon JVM args. [1]
Precedence (who wins if you set both?)
Kotlin Gradle plugin applies overrides in this order (later wins):
Gradle-daemon inheritance → kotlin.daemon.jvm.options → kotlin.daemon.jvmargs → kotlin { kotlinDaemonJvmArgs = ... } → per-task settings. [1]
Source
[1] Kotlin docs: “Compilation and caches in the Kotlin Gradle plugin” (Kotlin daemon JVM arguments, precedence, and configuration) (kotlinlang.org)
Citations:
🏁 Script executed:
cat -n ./gradle.properties | head -10Repository: futuredapp/kmp-futured-template
Length of output: 579
Replace kotlin.daemon.jvm.options with kotlin.daemon.jvmargs — the former is silently ignored in gradle.properties.
kotlin.daemon.jvm.options is a JVM system property meant to be passed via org.gradle.jvmargs (e.g., -Dkotlin.daemon.jvm.options=...), not a standalone gradle.properties key. The Kotlin Gradle Plugin reads kotlin.daemon.jvmargs from gradle.properties. As written, this MaxMetaspaceSize setting for the Kotlin daemon is never applied.
Proposed fix
-kotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g
+kotlin.daemon.jvmargs=-XX:MaxMetaspaceSize=1g🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@gradle.properties` at line 3, Replace the incorrect gradle.properties key
kotlin.daemon.jvm.options with the correct property kotlin.daemon.jvmargs so the
Kotlin Gradle Plugin applies the JVM argument; update the entry to use
kotlin.daemon.jvmargs and keep the value -XX:MaxMetaspaceSize=1g (ensuring any
existing org.gradle.jvmargs usage isn't duplicated) so the Kotlin daemon
receives the MaxMetaspaceSize setting.
| listOf( | ||
| iosX64(), | ||
| iosArm64(), | ||
| iosSimulatorArm64(), | ||
| ).forEach { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for iosX64 references in Kotlin/Gradle files
echo "=== Searching for iosX64 in Kotlin/KTS files ==="
rg -n "iosX64" --type=kotlin --type=kts
echo -e "\n=== Searching for iosX64 in YAML files ==="
rg -n "iosX64" --type=yaml
echo -e "\n=== Searching for iosX64 in all files ==="
rg -n "iosX64" --type-list | head -20 || rg -n "iosX64"
echo -e "\n=== Checking for x86_64 or Intel references ==="
rg -n "x86_64|intel|Intel" --type=yaml -g "*{ci,build,github,gitlab}*" | head -20Repository: futuredapp/kmp-futured-template
Length of output: 694
🏁 Script executed:
#!/bin/bash
# Look for CI/CD configuration files
echo "=== CI Configuration files found ==="
find . -maxdepth 2 -type f \( -name "*.yml" -o -name "*.yaml" -o -name "*.kts" -o -name "*.gradle" \) | grep -i -E "(ci|github|gitlab|build|gradle)" | head -20
echo -e "\n=== Checking for GitHub Actions workflows ==="
find . -path "*/.github/workflows/*" -type f 2>/dev/null | head -20
echo -e "\n=== Checking build.gradle.kts file context ==="
cat -n shared/app/build.gradle.kts | head -60Repository: futuredapp/kmp-futured-template
Length of output: 3295
🏁 Script executed:
#!/bin/bash
# Check GitHub Actions workflows for runner specifications
echo "=== Contents of on_pull_request.yml ==="
cat -n .github/workflows/on_pull_request.yml
echo -e "\n=== Contents of on_cron.yml ==="
cat -n .github/workflows/on_cron.yml
echo -e "\n=== Contents of on_release.yml ==="
cat -n .github/workflows/on_release.ymlRepository: futuredapp/kmp-futured-template
Length of output: 7337
🏁 Script executed:
#!/bin/bash
# Look for documentation files mentioning platforms
echo "=== Checking for README or CONTRIBUTING files ==="
find . -maxdepth 2 -type f \( -name "README*" -o -name "CONTRIBUTING*" -o -name "SETUP*" \) -o -path "./docs/*" -type f
echo -e "\n=== Searching for platform/Mac/Intel references in documentation ==="
rg -i "intel|x86_64|arm64|apple.silicon|mac.{0,5}setup" --type=markdown
echo -e "\n=== Checking .xcconfig files for simulator arch specs ==="
find . -name "*.xcconfig" -exec echo "--- File: {} ---" \; -exec cat {} \;Repository: futuredapp/kmp-futured-template
Length of output: 1299
🏁 Script executed:
cat -n ./README.mdRepository: futuredapp/kmp-futured-template
Length of output: 16279
Document Apple Silicon requirement for iOS development.
Removing iosX64() completely drops Intel Mac simulator support. iOS CI already runs on Apple Silicon via self-hosted runners (Futured-controlled), confirming the infrastructure decision. However, this template lacks documentation stating that iOS development requires an Apple Silicon Mac, which is important for contributors forking this template.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@shared/app/build.gradle.kts` around lines 46 - 49, The iOS target list now
only includes iosArm64() and iosSimulatorArm64(), which removes iosX64() and
thus drops Intel Mac simulator support; add a clear note explaining that iOS
development requires an Apple Silicon Mac (and that iosX64 was intentionally
omitted) so contributors know the requirement. Update the documentation (either
add a short comment above the list that contains iosArm64() and
iosSimulatorArm64() in build.gradle.kts and/or add a line in the repo README)
stating the Apple Silicon requirement, the rationale, and any CI note about
self-hosted Apple Silicon runners to guide contributors.
Replace findByName guards with lazy dependsOn resolution to fix implicit task dependency errors that break builds after dependency bumps. findByName only sees already-realized tasks, causing a race condition with lazily-registered KSP tasks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary by CodeRabbit
Chores
New Features
Compatibility
Chores
New Features
Compatibility