Conversation
|
Warning Rate limit exceeded@l2hyunwoo has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 13 minutes and 17 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
WalkthroughThis update migrates the project to Kotlin Multiplatform, introducing shared code for Android and iOS, platform-agnostic bitmap abstractions, and multiplatform Compose UI support. It restructures build scripts, adds platform-specific implementations, and updates dependency management to enable Compose Multiplatform development and cross-platform blur functionality. Changes
Sequence Diagram(s)sequenceDiagram
participant UI as Composable UI
participant Modifier as Modifier.cloudy (common)
participant Platform as Platform Impl (Android/iOS)
participant State as CloudyState
UI->>Modifier: Apply cloudy(radius, enabled, onStateChanged)
Modifier->>Platform: Delegate to platform-specific implementation
Platform->>Platform: Capture composable content as bitmap
Platform->>Platform: Apply blur (native algorithm/Core Image)
Platform->>State: Update CloudyState (Loading → Success/Error)
State-->>UI: Notify onStateChanged callback
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changesNo out-of-scope changes detected. All changes align with the linked issue objectives. Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (5)
cloudy/src/commonMain/kotlin/com/skydoves/cloudy/Cloudy.kt (1)
22-37: Remove duplicate KDoc comments.There are two sets of documentation comments describing the same function. Keep only one comprehensive version.
-/** - * `Modifier.cloudy()` is a blur modifier that applies blur effects to composables, - * compatible with all supported platforms. - * - * @param radius Radius of the blur along both the x and y axis. Must be non-negative. - * On Android, values > 25 are achieved through iterative passes which may affect performance. - * @param enabled Enabling the blur effects. - * @param onStateChanged Lambda function that will be invoked when the blur process has been updated. - */ /** * Applies a cross-platform blur effect to the current modifier. * * @param radius The blur radius in pixels for both the x and y axes. Must be non-negative. On Android, values above 25 may impact performance due to iterative passes. * @param enabled If false, disables the blur effect. * @param onStateChanged Callback invoked when the blur state changes. * @return A [Modifier] with the blur effect applied. */cloudy/src/commonMain/kotlin/com/skydoves/cloudy/CloudyState.kt (1)
58-58: Addpublicvisibility modifier for consistency.The
throwableproperty should have an explicitpublicmodifier to maintain consistency with the rest of the public API declarations in this file.- public data class Error(val throwable: Throwable) : CloudyState + public data class Error(public val throwable: Throwable) : CloudyStatecloudy/src/androidMain/kotlin/com/skydoves/cloudy/Cloudy.android.kt (1)
39-51: Remove redundant documentation block.This documentation block is redundant with the properly formatted one below (lines 52-61). The extra asterisks also cause formatting issues.
-/** - * Android implementation of the cloudy modifier that applies blur effects to composables. - * This is the actual implementation for the expect function declared in commonMain. - * * For Android 12+ devices in preview mode, it falls back to the platform's blur modifier. - * For runtime execution, it uses a custom implementation with graphics layers and - * native iterative blur processing for optimal performance. - * * The implementation captures the composable content in a graphics layer, applies - * iterative blur processing using native code, and overlays the result. - * * @param radius The blur radius in pixels (1-25). Higher values create more blur but take longer to process. - * @param enabled Whether the blur effect is enabled. When false, returns the original modifier unchanged. - * @param onStateChanged Callback that receives updates about the blur processing state. - * @return Modified Modifier with blur effect applied. - */cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt (1)
42-51: Remove redundant documentation block.Similar to the Android implementation, this documentation block is redundant with the properly formatted one below (lines 52-60).
-/** - * iOS implementation of the cloudy modifier that applies blur effects to composables. - * This is the actual implementation for the expect function declared in commonMain. - * * Uses Core Image filters for blur processing on iOS, with graphics layer content capture - * to blur the actual composable content instead of placeholder images. - * * @param radius The blur radius in pixels. Higher values create more blur. - * @param enabled Whether the blur effect is enabled. When false, returns the original modifier unchanged. - * @param onStateChanged Callback that receives updates about the blur processing state. - * @return Modified Modifier with blur effect applied. - */cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt (1)
184-187: Consider logging conversion failures for debugging.While returning placeholder images on failure maintains app stability, consider adding debug logging to help identify conversion issues during development.
} catch (_: Exception) { + // TODO: Add debug logging for conversion failures // Fallback to creating a basic placeholder createBasicPlaceholderUIImage(this.width, this.height) }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
.gitignore(1 hunks)build.gradle.kts(1 hunks)buildSrc/src/main/kotlin/com/skydoves/cloudy/ActiveArch.kt(1 hunks)cloudy/api/cloudy.api(1 hunks)cloudy/build.gradle.kts(1 hunks)cloudy/src/androidMain/kotlin/com/skydoves/cloudy/Cloudy.android.kt(3 hunks)cloudy/src/androidMain/kotlin/com/skydoves/cloudy/PlatformBitmap.android.kt(1 hunks)cloudy/src/androidMain/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt(6 hunks)cloudy/src/commonMain/kotlin/com/skydoves/cloudy/Cloudy.kt(1 hunks)cloudy/src/commonMain/kotlin/com/skydoves/cloudy/CloudyState.kt(1 hunks)cloudy/src/commonMain/kotlin/com/skydoves/cloudy/PlatformBitmap.kt(1 hunks)cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt(1 hunks)cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt(1 hunks)cloudy/src/main/kotlin/com/skydoves/cloudy/CloudyState.kt(0 hunks)gradle/libs.versions.toml(2 hunks)scripts/publish-module.gradle.kts(0 hunks)
💤 Files with no reviewable changes (2)
- scripts/publish-module.gradle.kts
- cloudy/src/main/kotlin/com/skydoves/cloudy/CloudyState.kt
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:12:51.545Z
Learning: User l2hyunwoo prefers to keep PRs focused on their primary objective and avoid scope creep. They acknowledge technical debt items but prefer to address them in separate PRs rather than expanding the current PR scope.
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
cloudy/src/commonMain/kotlin/com/skydoves/cloudy/CloudyState.kt (1)
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt (1)
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
cloudy/src/androidMain/kotlin/com/skydoves/cloudy/Cloudy.android.kt (1)
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
cloudy/src/commonMain/kotlin/com/skydoves/cloudy/Cloudy.kt (1)
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
cloudy/src/commonMain/kotlin/com/skydoves/cloudy/PlatformBitmap.kt (1)
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
cloudy/src/androidMain/kotlin/com/skydoves/cloudy/PlatformBitmap.android.kt (1)
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
cloudy/build.gradle.kts (1)
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
cloudy/src/androidMain/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt (1)
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt (1)
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
cloudy/api/cloudy.api (1)
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.799Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
🧬 Code Graph Analysis (1)
cloudy/src/androidMain/kotlin/com/skydoves/cloudy/Cloudy.android.kt (1)
cloudy/src/androidMain/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt (1)
iterativeBlur(379-406)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: build
- GitHub Check: API check
- GitHub Check: Spotless check
🔇 Additional comments (17)
.gitignore (1)
12-13: LGTM! Appropriate addition for multiplatform setup.Adding the
.kotlin/directory to ignore list is standard practice for Kotlin Multiplatform projects as it contains build artifacts.build.gradle.kts (1)
8-9: LGTM! Standard multiplatform plugin declarations.Adding the multiplatform plugin aliases with
apply falseis the correct approach for root build files, enabling subprojects to apply them as needed.buildSrc/src/main/kotlin/com/skydoves/cloudy/ActiveArch.kt (2)
6-25: Well-structured architecture detection enum.The
Archenum and companion object provide clean architecture detection for multiplatform builds. Good use of fallback toALLwhen no match is found.
27-35: Robust property reading implementation.The
activeArchextension property handles file existence checks, proper charset encoding, and environment variable fallback appropriately.cloudy/src/commonMain/kotlin/com/skydoves/cloudy/Cloudy.kt (1)
38-43: Excellent expect function declaration.The function signature is well-designed with appropriate parameter types, default values, and the
@IntRangeannotation for radius validation.cloudy/src/commonMain/kotlin/com/skydoves/cloudy/PlatformBitmap.kt (2)
24-40: Excellent multiplatform bitmap abstraction.The
PlatformBitmapexpect class provides a clean abstraction with appropriate immutability annotations and well-defined properties.
42-54: Well-designed extension functions.The
createCompatible()anddispose()extension functions provide clear resource management patterns that will work across platforms.cloudy/src/androidMain/kotlin/com/skydoves/cloudy/PlatformBitmap.android.kt (1)
21-76: LGTM! Well-implemented platform abstraction.The Android implementation properly handles bitmap lifecycle management with appropriate null safety checks and recycling logic. The extension functions provide clean conversion APIs.
cloudy/src/androidMain/kotlin/com/skydoves/cloudy/Cloudy.android.kt (1)
117-175: Excellent resource management and platform abstraction.The implementation properly:
- Migrates from Android
BitmaptoPlatformBitmapabstraction- Manages resource lifecycle with
dispose()calls- Handles state transitions correctly
- Provides descriptive error messages
cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt (2)
176-192: Implementation aligns with incremental approach.The simplified UIImage conversion is acknowledged in the comments. Based on previous discussions, I understand this is intentional technical debt to be addressed in a future PR focused on pixel conversion optimization.
204-225: Clean Core Image implementation.The Gaussian blur implementation properly uses Core Image APIs with appropriate error handling and null safety checks.
gradle/libs.versions.toml (1)
21-21: Compose Multiplatform version (1.8.2) is up-to-date
Confirmed that 1.8.2 is the latest stable release as of July 2025. No changes required.cloudy/api/cloudy.api (1)
34-42: API changes align well with multiplatform architecture.The migration from Android's
BitmaptoPlatformBitmapinCloudyState$Successis a clean abstraction that enables cross-platform compatibility.cloudy/build.gradle.kts (2)
43-59: Dynamic iOS target selection is well-implemented.The architecture-based target selection provides flexibility for different build environments and reduces unnecessary compilation overhead.
66-77: CMake configuration properly supports modern Android requirements.The C++17 standard and flexible page sizes flag ensure compatibility with recent Android versions.
cloudy/src/androidMain/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt (1)
379-406: Excellent fix for the iterative blur algorithm.The corrected logic properly handles blur radius decomposition:
- Correctly calculates full passes with integer division
- Applies remainder blur first when needed
- Eliminates previous off-by-one errors
This ensures accurate blur effects for radii greater than 25.
cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt (1)
201-256: Placeholder implementation acknowledged as known technical debt.As discussed in previous PRs, this synthetic gradient implementation is a temporary solution that will be replaced with actual pixel extraction in a future focused PR. The current implementation is sufficient for initial multiplatform support.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt (1)
42-60: Remove duplicate documentation comments.There are two documentation blocks for the same function. Keep only one comprehensive documentation block.
-/** - * iOS implementation of the cloudy modifier that applies blur effects to composables. - * This is the actual implementation for the expect function declared in commonMain. - * * Uses Core Image filters for blur processing on iOS, with graphics layer content capture - * to blur the actual composable content instead of placeholder images. - * * @param radius The blur radius in pixels. Higher values create more blur. - * @param enabled Whether the blur effect is enabled. When false, returns the original modifier unchanged. - * @param onStateChanged Callback that receives updates about the blur processing state. - * @return Modified Modifier with blur effect applied. - */ /** * Applies a Gaussian blur effect to the composable content using Core Image when enabled. * * @param radius The blur radius in points. Must be non-negative. * @param enabled If false, no blur is applied and the modifier is unchanged. * @param onStateChanged Callback invoked with the current blur processing state. * @return The modifier with the blur effect applied if enabled; otherwise, the original modifier. * @throws IllegalArgumentException if radius is negative. */
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
.gitignore(1 hunks)build.gradle.kts(1 hunks)buildSrc/src/main/kotlin/com/skydoves/cloudy/ActiveArch.kt(1 hunks)cloudy/api/cloudy.api(1 hunks)cloudy/build.gradle.kts(1 hunks)cloudy/src/androidMain/kotlin/com/skydoves/cloudy/Cloudy.android.kt(4 hunks)cloudy/src/androidMain/kotlin/com/skydoves/cloudy/PlatformBitmap.android.kt(1 hunks)cloudy/src/androidMain/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt(6 hunks)cloudy/src/androidUnitTest/kotlin/com/skydoves/cloudy/CloudyStateTest.kt(1 hunks)cloudy/src/androidUnitTest/kotlin/com/skydoves/cloudy/PlatformBitmapTest.kt(1 hunks)cloudy/src/commonMain/kotlin/com/skydoves/cloudy/Cloudy.kt(1 hunks)cloudy/src/commonMain/kotlin/com/skydoves/cloudy/CloudyState.kt(1 hunks)cloudy/src/commonMain/kotlin/com/skydoves/cloudy/PlatformBitmap.kt(1 hunks)cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt(1 hunks)cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt(1 hunks)cloudy/src/iosTest/kotlin/com/skydoves/cloudy/CloudyStateTest.kt(1 hunks)cloudy/src/iosTest/kotlin/com/skydoves/cloudy/PlatformBitmapTest.kt(1 hunks)cloudy/src/iosTest/kotlin/com/skydoves/cloudy/TestUtils.kt(1 hunks)cloudy/src/main/kotlin/com/skydoves/cloudy/CloudyState.kt(0 hunks)gradle/libs.versions.toml(2 hunks)scripts/publish-module.gradle.kts(0 hunks)
💤 Files with no reviewable changes (2)
- scripts/publish-module.gradle.kts
- cloudy/src/main/kotlin/com/skydoves/cloudy/CloudyState.kt
✅ Files skipped from review due to trivial changes (1)
- cloudy/src/commonMain/kotlin/com/skydoves/cloudy/Cloudy.kt
🚧 Files skipped from review as they are similar to previous changes (9)
- build.gradle.kts
- .gitignore
- cloudy/src/commonMain/kotlin/com/skydoves/cloudy/PlatformBitmap.kt
- cloudy/src/commonMain/kotlin/com/skydoves/cloudy/CloudyState.kt
- cloudy/src/androidMain/kotlin/com/skydoves/cloudy/PlatformBitmap.android.kt
- buildSrc/src/main/kotlin/com/skydoves/cloudy/ActiveArch.kt
- cloudy/src/androidMain/kotlin/com/skydoves/cloudy/Cloudy.android.kt
- cloudy/build.gradle.kts
- cloudy/api/cloudy.api
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.820Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:12:51.564Z
Learning: User l2hyunwoo prefers to keep PRs focused on their primary objective and avoid scope creep. They acknowledge technical debt items but prefer to address them in separate PRs rather than expanding the current PR scope.
📚 Learning: in the cloudy project, the uiimage.asimagebitmap() function in cloudy/src/iosmain/kotlin/com/skydove...
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.820Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
Applied to files:
cloudy/src/iosTest/kotlin/com/skydoves/cloudy/CloudyStateTest.ktcloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.ktcloudy/src/androidUnitTest/kotlin/com/skydoves/cloudy/PlatformBitmapTest.ktcloudy/src/iosTest/kotlin/com/skydoves/cloudy/TestUtils.ktcloudy/src/androidUnitTest/kotlin/com/skydoves/cloudy/CloudyStateTest.ktcloudy/src/iosTest/kotlin/com/skydoves/cloudy/PlatformBitmapTest.ktcloudy/src/androidMain/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.ktcloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt
🧬 Code Graph Analysis (1)
cloudy/src/iosTest/kotlin/com/skydoves/cloudy/CloudyStateTest.kt (1)
cloudy/src/iosTest/kotlin/com/skydoves/cloudy/TestUtils.kt (1)
createTestPlatformBitmap(29-31)
🔇 Additional comments (41)
cloudy/src/androidMain/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt (9)
236-243: LGTM! Comprehensive KDoc documentation added.The detailed KDoc for
Rgba3dArrayclearly documents the class purpose, parameters, and behavior. The documentation helps understand the 3D RGBA data structure and its indexed access pattern.
262-270: Excellent documentation for internal method.The KDoc for
indexOfVectorprovides clear documentation of the coordinate-to-index calculation, including parameter descriptions and exception behavior. This is particularly valuable for understanding the 3D array indexing logic.
279-288: Well-documented validation function.The KDoc clearly explains the bitmap validation requirements, parameters, and exception conditions. This documentation will help developers understand when and why bitmap validation might fail.
314-319: Clear documentation for bitmap creation utility.The KDoc succinctly describes the purpose and behavior of
createCompatibleBitmap, making it easy to understand its role in creating matching bitmap instances.
323-327: Good documentation for validation utility.The KDoc clearly explains the restriction validation logic and error conditions, helping developers understand the bounds checking requirements.
349-357: Comprehensive documentation for pixel size calculation.The KDoc clearly explains the supported bitmap configurations and their corresponding byte sizes, along with exception behavior for unsupported formats.
368-377: Excellent documentation for complex blur algorithm.The KDoc provides a clear explanation of the iterative blur strategy, explaining why multiple passes are needed and how the algorithm handles radius limits.
383-394: Critical fix: Corrected blur radius calculation.The iterative blur logic has been properly corrected to fix off-by-one errors:
iterate = radius / 25correctly calculates full passesremainder = radius % 25correctly calculates remaining radius- Proper handling when remainder is 0 vs non-zero
This fix ensures accurate blur radius application.
396-402: LGTM! Correct iterative application.The use of
repeat(iterate)correctly applies the calculated number of full 25-radius blur passes. The logic properly chains the blur operations through the bitmap variable.gradle/libs.versions.toml (4)
21-26: Good addition of multiplatform dependencies.The new version entries for Compose Multiplatform (1.8.2) and testing libraries (junit4, kotlinx-coroutines-test, mockito) provide proper version management for the multiplatform migration.
32-33: LGTM! Essential multiplatform plugins added.The addition of
kotlin-multiplatformandcompose-multiplatformplugins are correctly configured and essential for the multiplatform support objective.
58-71: Comprehensive multiplatform library support.The new library entries provide excellent coverage for:
- Compose Multiplatform runtime and UI components
- Kotlin test utilities
- AndroidX Compose testing libraries
- Mockito testing framework
These additions align well with the multiplatform testing strategy evidenced in the other files.
2-2: No action required: AGP 8.12.0 compatibility confirmedAndroid Gradle Plugin 8.12.0 is fully compatible with Kotlin 2.2.0 and Compose Multiplatform 1.8.2. You can continue using
agp = "8.12.0"in gradle/libs.versions.toml as is.
For optimal alignment, ensure the Compose Compiler Gradle plugin version matches Kotlin 2.2.0.cloudy/src/iosTest/kotlin/com/skydoves/cloudy/TestUtils.kt (3)
16-21: Proper foreign API handling.The
@file:OptIn(ExperimentalForeignApi::class)annotation and import are correctly used for interacting with iOS platform APIs.
29-31: Clean test utility design.The
createTestPlatformBitmapfunction provides a simple, focused interface for creating test bitmaps by delegating to the more specificcreateTestUIImagefunction.
43-48: Robust UIImage creation with proper error handling.The
createTestUIImagefunction correctly:
- Uses proper iOS graphics APIs
- Handles the graphics context lifecycle properly
- Provides fallback to empty UIImage if creation fails
- Uses appropriate parameter types and scaling
cloudy/src/iosTest/kotlin/com/skydoves/cloudy/CloudyStateTest.kt (6)
25-30: LGTM! Proper singleton validation.The test correctly verifies that
CloudyState.Nothingmaintains singleton behavior using reference equality (===).
32-37: LGTM! Consistent singleton testing.The test correctly verifies that
CloudyState.Loadingmaintains singleton behavior, consistent with the Nothing state test.
39-44: Good integration with test utilities.The test properly uses
createTestPlatformBitmapfrom the test utilities and validates that the Success state correctly holds the bitmap reference.
46-51: Comprehensive error state testing.The test properly validates that the Error state correctly holds and returns the provided throwable.
53-59: LGTM! Proper equality testing.The test correctly verifies that Success states with the same bitmap are considered equal, which is important for state management.
61-68: Thorough inequality validation.The test properly validates that Success states with different bitmaps are not equal, completing the equality testing coverage.
cloudy/src/iosTest/kotlin/com/skydoves/cloudy/PlatformBitmapTest.kt (5)
24-31: LGTM! Proper dimension validation.The test correctly validates that PlatformBitmap reports the correct width and height from the underlying UIImage.
33-37: Good iOS-specific behavior validation.The test correctly validates that iOS PlatformBitmap instances are always recyclable, which aligns with the iOS platform behavior where bitmap recycling is handled automatically.
39-45: Thorough compatibility testing.The test properly validates that
createCompatible()produces a new bitmap with the same dimensions, which is essential for the blur operations.
47-52: Robust dispose behavior testing.The test correctly validates that
dispose()can be called multiple times without throwing exceptions, which is important for safe resource management in the multiplatform context.
54-59: Good extension method validation.The test properly validates that the
toUIImage()extension returns the correct underlying UIImage, ensuring proper platform integration.cloudy/src/androidUnitTest/kotlin/com/skydoves/cloudy/PlatformBitmapTest.kt (5)
33-47: Well-structured test for basic properties.The test comprehensively verifies that PlatformBitmap correctly exposes width and height from the underlying Android Bitmap, with appropriate mocking of all required properties.
49-86: Excellent edge case coverage for recyclability.The three tests comprehensively cover all recyclability scenarios based on the bitmap's mutable and recycled states, ensuring the isRecyclable property behaves correctly in all cases.
88-144: Proper static method mocking and comprehensive createCompatible testing.Excellent use of mockStatic with try-with-resources pattern. The tests thoroughly verify that createCompatible preserves both dimensions and bitmap configuration.
146-177: Thorough dispose() method testing.Good coverage of both the normal disposal case and the edge case of already-recycled bitmaps. The use of
verify(mockBitmap, times(0)).recycle()correctly ensures no redundant recycling occurs.
179-205: Correct extension function testing with proper identity checks.Good use of
assertSameto ensure the extension functions maintain bitmap instance identity during wrapping/unwrapping operations.cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt (4)
79-110: Well-structured modifier element implementation.The CloudyModifierNodeElement correctly implements the ModifierNodeElement interface with proper data class semantics and inspector support.
151-152: Known limitation: placeholder image conversion.The
toUIImage().asImageBitmap()conversion currently uses a synthetic gradient implementation rather than actual pixel extraction, as noted in the learnings. This is acknowledged technical debt to be addressed in a future PR.
204-225: Robust Core Image blur implementation.Excellent error handling with proper null checks and exception catching. The CIGaussianBlur filter usage is correct and follows iOS best practices.
20-20: Confirm IntRange annotation compatibility on iOS
The use of@IntRange(from = 0)fromandroidx.annotationshows up in both your common and iOS‐specific code, but I didn’t find an explicitandroidx.annotationdependency in your Gradle scripts. Without a dedicated multiplatform artifact, this annotation may not be available when compiling for iOS.• Verify that
androidx.annotation:IntRangeis pulled in transitively for all targets (including iOS).
• If not, consider replacing it with a Kotlin native or custom multiplatform annotation incommonMainto enforce the non-negative radius.cloudy/src/androidUnitTest/kotlin/com/skydoves/cloudy/CloudyStateTest.kt (2)
29-43: Correct singleton verification for stateless variants.Good use of
assertSameto verify that Nothing and Loading states are true singletons, which is important for performance and memory efficiency.
45-85: Comprehensive Success state testing.Excellent coverage including the null bitmap case and proper equality semantics based on bitmap identity.
cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt (3)
48-56: Correct iOS-specific bitmap property implementations.Good adaptation to iOS conventions:
- Width/height properly account for retina display scale
- isRecyclable correctly reflects iOS's ARC memory management
98-188: Documented placeholder implementation for ImageBitmap to UIImage conversion.The implementation creates a representative image by sampling colors and generating patterns. The extensive comments clearly document this as an approximation. This aligns with the known technical debt to be addressed in a future PR focused on pixel conversion optimization.
190-256: Known placeholder implementation for UIImage to ImageBitmap conversion.As documented in the comments and confirmed by learnings, this generates synthetic gradients rather than extracting actual CGImage pixels. This technical debt is acknowledged and will be addressed in a future PR focused on pixel conversion optimization.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt (2)
144-144: Consider using a more appropriate dispatcherFor CPU-intensive image processing operations, consider using
Dispatchers.IOinstead ofDispatchers.Defaultto avoid blocking the default dispatcher pool.- coroutineScope.launch(Dispatchers.Default) { + coroutineScope.launch(Dispatchers.IO) {
178-182: Document the temporary nature of the placeholder implementationConsider adding a TODO comment to track the future replacement of this placeholder implementation with actual graphics layer capture.
/** * Creates a placeholder bitmap representing the composable content. * This is a temporary solution until graphics layer capture is available on iOS. + * TODO: Replace with actual graphics layer capture when available in Compose iOS */ private fun createPlaceholderBitmap(width: Int, height: Int): ImageBitmap? {
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt(1 hunks)cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.820Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:12:51.564Z
Learning: User l2hyunwoo prefers to keep PRs focused on their primary objective and avoid scope creep. They acknowledge technical debt items but prefer to address them in separate PRs rather than expanding the current PR scope.
📚 Learning: in the cloudy project, the uiimage.asimagebitmap() function in cloudy/src/iosmain/kotlin/com/skydove...
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.820Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
Applied to files:
cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.ktcloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt
⏰ 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). (3)
- GitHub Check: Spotless check
- GitHub Check: build
- GitHub Check: API check
🔇 Additional comments (4)
cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt (1)
71-102: LGTM!The
CloudyModifierNodeElementimplementation correctly follows Compose Modifier patterns with proper inspector properties and node lifecycle management.cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt (3)
53-72: LGTM!The
PlatformBitmapimplementation correctly handles iOS UIImage wrapping with proper scale-aware dimension calculations.
74-98: Platform-appropriate implementationsBoth
createCompatible()anddispose()are correctly implemented for iOS, with clear documentation explaining the ARC-based memory management approach.
199-288: Excellent pixel extraction implementationThis implementation properly extracts actual CGImage pixels instead of using synthetic gradients, addressing the technical debt mentioned in previous reviews. The RGBA to BGRA conversion for Skia compatibility is correctly handled.
| * @return The blurred bitmap, or null if the blur operation fails. | ||
| */ | ||
| @OptIn(ExperimentalForeignApi::class) | ||
| private suspend fun createBlurredBitmapFromContent( |
There was a problem hiding this comment.
Remove redundant @OptIn annotation
This annotation is unnecessary as applyGaussianBlur already has the same annotation at line 254.
-@OptIn(ExperimentalForeignApi::class)
private suspend fun createBlurredBitmapFromContent(🤖 Prompt for AI Agents
In cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt at line 223,
remove the redundant @OptIn annotation from the createBlurredBitmapFromContent
function since the applyGaussianBlur function at line 254 already has this
annotation, making it unnecessary here.
| // This method is kept for API consistency across platforms | ||
| } | ||
|
|
||
| /**** |
There was a problem hiding this comment.
Fix documentation comment syntax
-/****
+/**🤖 Prompt for AI Agents
In cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt at line
100, the documentation comment syntax is incorrect. Replace the current /***
style comment with the proper Kotlin documentation comment syntax /** to ensure
it is recognized as a valid KDoc comment.
17786f0 to
473e202
Compare
Update buildSrc/src/main/kotlin/com/skydoves/cloudy/ActiveArch.kt Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
[#53] revert for resolve build issue
Docstrings generation was requested by @l2hyunwoo. * #63 (comment) The following files were modified: * `buildSrc/src/main/kotlin/com/skydoves/cloudy/ActiveArch.kt` * `cloudy/src/androidMain/kotlin/com/skydoves/cloudy/Cloudy.android.kt` * `cloudy/src/androidMain/kotlin/com/skydoves/cloudy/PlatformBitmap.android.kt` * `cloudy/src/androidMain/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt` * `cloudy/src/commonMain/kotlin/com/skydoves/cloudy/Cloudy.kt` * `cloudy/src/commonMain/kotlin/com/skydoves/cloudy/PlatformBitmap.kt` * `cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt` * `cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
- Add iOS targets (iosX64, iosArm64, iosSimulatorArm64) - Configure ComposeApp framework for iOS - Set up multiplatform source sets (androidMain, commonMain, iosMain) - Move demo code from cloudy module to app/commonMain - Add MainViewController for iOS - Add platform-specific UUID implementations
- Remove all demo code and dependencies from cloudy module - Remove Landscapist and Material dependencies (moved to app module) - Keep only core Cloudy blur functionality - Make cloudy module a pure library without app-specific code
- Remove old src/main directory structure - Clean up old Android-specific code in app module - Prepare for new multiplatform source set layout
- Add Coil 3.2.0 dependencies for Compose Multiplatform - Add landscapist-coil3 for cross-platform image loading - Replace Android-specific GlideImage with KMP-compatible CoilImage
- Remove Kotlin source files and Gradle configuration from iosApp - Update ContentView.swift to use ComposeApp framework - Remove iosApp from Gradle settings (now pure Xcode project)
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
cloudy/build.gradle.kts (1)
20-26: Redundant Compose compiler plugin
org.jetbrains.compose(Compose Multiplatform) already applies the Compose compiler plugin internally. Addingorg.jetbrains.kotlin.plugin.composeseparately introduces duplicated compiler plugin registrations and longer configuration times.Safe to drop the explicit line:
- id(libs.plugins.compose.compiler.get().pluginId)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
app/src/androidMain/res/drawable/poster.pngis excluded by!**/*.pngapp/src/commonMain/composeResources/drawable/poster.pngis excluded by!**/*.png
📒 Files selected for processing (44)
.gitignore(1 hunks)app/build.gradle.kts(1 hunks)app/src/androidMain/kotlin/com/skydoves/cloudydemo/MainActivity.kt(1 hunks)app/src/androidMain/kotlin/demo/model/Poster.android.kt(1 hunks)app/src/commonMain/kotlin/demo/Main.kt(5 hunks)app/src/commonMain/kotlin/demo/model/MockUtil.kt(2 hunks)app/src/commonMain/kotlin/demo/model/Poster.kt(1 hunks)app/src/commonMain/kotlin/demo/theme/Color.kt(1 hunks)app/src/commonMain/kotlin/demo/theme/PosterTheme.kt(3 hunks)app/src/commonMain/kotlin/demo/theme/Type.kt(1 hunks)app/src/iosMain/kotlin/com/skydoves/cloudydemo/MainViewController.kt(1 hunks)app/src/iosMain/kotlin/demo/model/Poster.ios.kt(1 hunks)app/src/main/kotlin/com/skydoves/cloudydemo/custom/StaggeredVerticalGrid.kt(0 hunks)app/src/main/kotlin/com/skydoves/cloudydemo/posters/HomePosters.kt(0 hunks)app/src/main/kotlin/com/skydoves/cloudydemo/posters/LibraryPosters.kt(0 hunks)app/src/main/kotlin/com/skydoves/cloudydemo/posters/RadioPosters.kt(0 hunks)app/src/main/kotlin/com/skydoves/cloudydemo/theme/Type.kt(0 hunks)build.gradle.kts(1 hunks)buildSrc/src/main/kotlin/com/skydoves/cloudy/ActiveArch.kt(1 hunks)cloudy/api/cloudy.api(1 hunks)cloudy/build.gradle.kts(1 hunks)cloudy/src/androidMain/kotlin/com/skydoves/cloudy/Cloudy.android.kt(4 hunks)cloudy/src/androidMain/kotlin/com/skydoves/cloudy/PlatformBitmap.android.kt(1 hunks)cloudy/src/androidMain/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt(6 hunks)cloudy/src/androidUnitTest/kotlin/com/skydoves/cloudy/CloudyStateTest.kt(1 hunks)cloudy/src/androidUnitTest/kotlin/com/skydoves/cloudy/PlatformBitmapTest.kt(1 hunks)cloudy/src/commonMain/kotlin/com/skydoves/cloudy/Cloudy.kt(1 hunks)cloudy/src/commonMain/kotlin/com/skydoves/cloudy/CloudyState.kt(1 hunks)cloudy/src/commonMain/kotlin/com/skydoves/cloudy/PlatformBitmap.kt(1 hunks)cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt(1 hunks)cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt(1 hunks)cloudy/src/iosTest/kotlin/com/skydoves/cloudy/CloudyStateTest.kt(1 hunks)cloudy/src/iosTest/kotlin/com/skydoves/cloudy/PlatformBitmapTest.kt(1 hunks)cloudy/src/iosTest/kotlin/com/skydoves/cloudy/TestUtils.kt(1 hunks)cloudy/src/main/kotlin/com/skydoves/cloudy/CloudyState.kt(0 hunks)gradle/libs.versions.toml(2 hunks)iosApp/iosApp.xcodeproj/project.pbxproj(1 hunks)iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json(1 hunks)iosApp/iosApp/Assets.xcassets/Contents.json(1 hunks)iosApp/iosApp/ContentView.swift(1 hunks)iosApp/iosApp/Info.plist(1 hunks)iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json(1 hunks)iosApp/iosApp/iOSApp.swift(1 hunks)scripts/publish-module.gradle.kts(0 hunks)
💤 Files with no reviewable changes (7)
- scripts/publish-module.gradle.kts
- app/src/main/kotlin/com/skydoves/cloudydemo/theme/Type.kt
- cloudy/src/main/kotlin/com/skydoves/cloudy/CloudyState.kt
- app/src/main/kotlin/com/skydoves/cloudydemo/posters/RadioPosters.kt
- app/src/main/kotlin/com/skydoves/cloudydemo/custom/StaggeredVerticalGrid.kt
- app/src/main/kotlin/com/skydoves/cloudydemo/posters/HomePosters.kt
- app/src/main/kotlin/com/skydoves/cloudydemo/posters/LibraryPosters.kt
✅ Files skipped from review due to trivial changes (6)
- app/src/iosMain/kotlin/com/skydoves/cloudydemo/MainViewController.kt
- app/src/commonMain/kotlin/demo/theme/Type.kt
- iosApp/iosApp/Info.plist
- iosApp/iosApp/ContentView.swift
- cloudy/src/commonMain/kotlin/com/skydoves/cloudy/Cloudy.kt
- app/src/commonMain/kotlin/demo/model/MockUtil.kt
🚧 Files skipped from review as they are similar to previous changes (28)
- app/src/commonMain/kotlin/demo/theme/PosterTheme.kt
- build.gradle.kts
- iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json
- iosApp/iosApp/Assets.xcassets/Contents.json
- .gitignore
- app/src/androidMain/kotlin/com/skydoves/cloudydemo/MainActivity.kt
- app/src/androidMain/kotlin/demo/model/Poster.android.kt
- app/src/iosMain/kotlin/demo/model/Poster.ios.kt
- app/src/commonMain/kotlin/demo/model/Poster.kt
- cloudy/src/iosTest/kotlin/com/skydoves/cloudy/TestUtils.kt
- iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json
- buildSrc/src/main/kotlin/com/skydoves/cloudy/ActiveArch.kt
- cloudy/src/iosTest/kotlin/com/skydoves/cloudy/CloudyStateTest.kt
- cloudy/src/commonMain/kotlin/com/skydoves/cloudy/CloudyState.kt
- cloudy/src/androidUnitTest/kotlin/com/skydoves/cloudy/CloudyStateTest.kt
- cloudy/src/androidMain/kotlin/com/skydoves/cloudy/PlatformBitmap.android.kt
- cloudy/src/iosTest/kotlin/com/skydoves/cloudy/PlatformBitmapTest.kt
- iosApp/iosApp.xcodeproj/project.pbxproj
- app/src/commonMain/kotlin/demo/theme/Color.kt
- app/src/commonMain/kotlin/demo/Main.kt
- app/build.gradle.kts
- cloudy/src/androidUnitTest/kotlin/com/skydoves/cloudy/PlatformBitmapTest.kt
- cloudy/src/androidMain/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt
- cloudy/src/commonMain/kotlin/com/skydoves/cloudy/PlatformBitmap.kt
- cloudy/api/cloudy.api
- cloudy/src/androidMain/kotlin/com/skydoves/cloudy/Cloudy.android.kt
- cloudy/src/iosMain/kotlin/com/skydoves/cloudy/Cloudy.ios.kt
- cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.820Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:12:51.564Z
Learning: User l2hyunwoo prefers to keep PRs focused on their primary objective and avoid scope creep. They acknowledge technical debt items but prefer to address them in separate PRs rather than expanding the current PR scope.
📚 Learning: in the cloudy project, the uiimage.asimagebitmap() function in cloudy/src/iosmain/kotlin/com/skydove...
Learnt from: l2hyunwoo
PR: skydoves/Cloudy#63
File: cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt:0-0
Timestamp: 2025-07-06T06:13:55.820Z
Learning: In the Cloudy project, the UIImage.asImageBitmap() function in cloudy/src/iosMain/kotlin/com/skydoves/cloudy/PlatformBitmap.ios.kt currently uses a placeholder implementation that generates synthetic gradients instead of extracting actual CGImage pixels. This is known technical debt that should be addressed in a future PR focused on pixel conversion optimization.
Applied to files:
cloudy/build.gradle.kts
🪛 SwiftLint (0.57.0)
iosApp/iosApp/iOSApp.swift
[Error] 4-4: Type name 'iOSApp' should start with an uppercase character
(type_name)
⏰ 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). (3)
- GitHub Check: API check
- GitHub Check: build
- GitHub Check: Spotless check
🔇 Additional comments (5)
iosApp/iosApp/iOSApp.swift (3)
1-1: LGTM!Standard SwiftUI import for the app entry point.
3-4: Type name follows iOS conventions correctly.The SwiftLint warning about the type name is a false positive.
iOSAppfollows established iOS naming conventions where "iOS" is a proper noun that traditionally starts with lowercase 'i' followed by uppercase 'O' and 'S'. This is consistent with Apple's own naming patterns (e.g.,iOS,iOSMain, etc.).
5-9: Clean SwiftUI App structure implementation.The implementation correctly follows SwiftUI App protocol conventions with a
WindowGrouphosting theContentView. This establishes the proper entry point for the iOS side of the Compose Multiplatform integration, allowing the Kotlin Compose UI to be displayed through the ContentView bridge.cloudy/build.gradle.kts (1)
31-38: Verify compiler flag-Xexpect-actual-classes
-Xexpect-actual-classeswas an experimental flag and has been removed/renamed in recent Kotlin 2.2 nightly builds. If you bump Kotlin further this will break the build. Double-check its necessity or gate it behind a Kotlin-version check.gradle/libs.versions.toml (1)
59-63: Potential duplication between JetBrains-Compose and AndroidX Compose artifacts
compose-runtime/foundation/uifrom JetBrains Compose (lines 59-63) and their AndroidX counterparts (lines 44-49) ship identical code but with different Maven coordinates. Mixing them in the same source-set can lead to duplicate classes and packaging conflicts.Confirm that:
• JetBrains Compose libs are used for common/desktop/iOS source-sets.
• Android source-sets depend exclusively on AndroidX Compose libs.If not, restrict each set of coordinates to the appropriate platform-specific source-set to avoid runtime and packaging clashes.
| android { | ||
| compileSdk = Configuration.compileSdk | ||
| namespace = "com.skydoves.cloudy" | ||
| defaultConfig { | ||
| minSdk = Configuration.minSdk | ||
| externalNativeBuild { | ||
| cmake { | ||
| cppFlags += "-std=c++17" | ||
| arguments += listOf("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON") | ||
| } | ||
| } | ||
| } | ||
| externalNativeBuild { | ||
| cmake { | ||
| cppFlags += "-std=c++17" | ||
| arguments += listOf("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON") | ||
| path = file("src/main/cpp/CMakeLists.txt") | ||
| } | ||
| } | ||
| } | ||
| externalNativeBuild { | ||
| cmake { | ||
| path = file("src/main/cpp/CMakeLists.txt") | ||
|
|
||
| buildFeatures { | ||
| compose = true | ||
| } | ||
| } | ||
|
|
||
| buildFeatures { | ||
| compose = true | ||
| } | ||
| packaging { | ||
| resources { | ||
| excludes.add("/META-INF/{AL2.0,LGPL2.1}") | ||
| } | ||
| } | ||
|
|
||
| packaging { | ||
| resources { | ||
| excludes.add("/META-INF/{AL2.0,LGPL2.1}") | ||
| sourceSets { | ||
| getByName("main") { | ||
| assets.srcDirs("src/androidMain/assets") | ||
| java.srcDirs("src/androidMain/kotlin") | ||
| res.srcDirs("src/androidMain/res") | ||
| } | ||
| getByName("test") { | ||
| assets.srcDirs("src/androidUnitTest/assets") | ||
| java.srcDirs("src/androidUnitTest/kotlin") | ||
| res.srcDirs("src/androidUnitTest/res") | ||
| } | ||
| } |
There was a problem hiding this comment.
android {} block is misplaced – move it out of the kotlin {} scope
The android { … } DSL belongs to the Android Gradle plugin (com.android.library) and must be declared at the module level, not inside the Kotlin Multiplatform kotlin {} block.
Keeping it nested will make Gradle treat it as a Kotlin target-specific configuration and the properties such as compileSdk, defaultConfig, externalNativeBuild, buildFeatures, packaging, and sourceSets will simply be ignored, leading to missing compileSdk and other essential settings at build time.
-kotlin {
- …
- android {
- compileSdk = …
- …
- }
-}
+
+kotlin {
+ … // keep KMP targets & source-sets
+}
+
+android { // <-- move to top-level
+ compileSdk = Configuration.compileSdk
+ namespace = "com.skydoves.cloudy"
+ defaultConfig {
+ minSdk = Configuration.minSdk
+ …
+ }
+ …
+}[fatal build-breaking issue]
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In cloudy/build.gradle.kts between lines 61 and 100, the android { } block is
incorrectly placed inside the kotlin { } block. This causes Gradle to ignore
essential Android build configurations like compileSdk and defaultConfig. To fix
this, move the entire android { } block out of the kotlin { } scope so it is
declared at the module level, ensuring all Android Gradle plugin settings are
properly applied.
| landscapist-coil = { group = "com.github.skydoves", name = "landscapist-coil3", version.ref = "landscapist" } | ||
| coil = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" } | ||
| coil-network = { group = "io.coil-kt.coil3", name = "coil-network-ktor3", version.ref = "coil" } |
There was a problem hiding this comment.
Incorrect Maven coordinates for Coil 3 artifacts
The group id should be io.coil-kt, not io.coil-kt.coil3. Using the wrong coordinates will make Gradle fail to resolve the dependency.
-landscapist-coil = { group = "com.github.skydoves", name = "landscapist-coil3", version.ref = "landscapist" }
-coil = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" }
-coil-network = { group = "io.coil-kt.coil3", name = "coil-network-ktor3", version.ref = "coil" }
+
+landscapist-coil = { group = "com.github.skydoves", name = "landscapist-coil3", version.ref = "landscapist" }
+coil = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" }
+coil-network = { group = "io.coil-kt", name = "coil-network-ktor", version.ref = "coil" }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| landscapist-coil = { group = "com.github.skydoves", name = "landscapist-coil3", version.ref = "landscapist" } | |
| coil = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" } | |
| coil-network = { group = "io.coil-kt.coil3", name = "coil-network-ktor3", version.ref = "coil" } | |
| landscapist-coil = { group = "com.github.skydoves", name = "landscapist-coil3", version.ref = "landscapist" } | |
| coil = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" } | |
| coil-network = { group = "io.coil-kt", name = "coil-network-ktor", version.ref = "coil" } |
🤖 Prompt for AI Agents
In gradle/libs.versions.toml around lines 66 to 68, the group id for the Coil 3
dependencies is incorrectly set to "io.coil-kt.coil3". Update the group id to
"io.coil-kt" for both "coil" and "coil-network" entries to ensure Gradle can
correctly resolve these dependencies.
🎯 Goal
🛠 Implementation details
✍️ Explain examples
Explain examples with code for this updates.
Preparing a pull request for review
Ensure your change is properly formatted by running:
Then dump binary API of this library that is public in sense of Kotlin visibilities and ensures that the public binary API wasn't changed in a way that make this change binary incompatible.
Please correct any failures before requesting a review.
Code reviews
All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult GitHub Help for more information on using pull requests.
Summary by CodeRabbit
New Features
Improvements
Refactor
Chores
Bug Fixes