Conversation
- Updated Gradle from 8.9 to 8.11.1 - Updated AGP from 8.7.2 to 8.10.1 - Updated Kotlin from 1.9.0 to 2.1.21 - Updated lifecycleRuntimeKtx from 2.7.0 to 2.9.0 - Updated composeMultiplatform from 1.8.0 to 1.8.1 - Removed example tests. - Replaced AndroidX Compose dependencies with Jetpack Compose Multiplatform dependencies. - Added documentation to NumberField composable. - Minor UI update in MainActivity to display NumberField value.
- Renamed iOS app from Rickpository to Droidcore. - Updated iOS ContentView to ignore all safe areas. - Added `kotlin.native.cacheKind=none` to `gradle.properties`. - Downgraded Kotlin version from 2.1.21 to 2.1.20. - Implemented initial iOS functionality for `NetworkImage` component. - Added iOS specific build files and user data to .gitignore. - Created `contents.xcworkspacedata` for iOS project.
- Added NeoToast, a simple toast component that is available for both Android and iOS. - Added CustomCarousel, a simple and lightweight custom carousel component. - Added FlipCard component. - Added ContextPlatform for context handling. - Added an enabled parameter to NeoTextField.
The Maven publication configuration in `droidcore/build.gradle.kts` has been refactored. Instead of creating a new publication named "maven", the existing publications are now configured directly using `publishing.publications.all`. The `groupId`, `artifactId`, and `version` are set for all publications.
- Added GitHub workflow to publish library to Maven Central. - Updated Maven Publish plugin to version 0.30.0. - Configured Maven publishing details in `droidcore/build.gradle.kts`. - Updated `MainActivity.kt` to use `org.jetbrains.compose.ui.tooling.preview.Preview`. - Removed unused imports and commented out wallpaper scheme in `MainActivity.kt`.
There was a problem hiding this comment.
Summary of Changes
Hello @laetuz, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request represents a significant architectural shift for the Droidcore library, transitioning it from an Android-only library to a Kotlin Multiplatform library. This migration facilitates code sharing between Android and iOS, streamlines UI development with Compose Multiplatform, and introduces new versatile UI components, ultimately broadening the library's applicability and maintainability.
Highlights
- Kotlin Multiplatform Migration: The
Droidcorelibrary and its sampleappmodule have been migrated to Kotlin Multiplatform, enabling shared UI components and logic across Android and iOS platforms. This includes extensive updates to Gradle configurations and project structure. - New UI Components: Two new Compose Multiplatform components,
FlipCard(a horizontally flippable card with animations) andCustomCarousel(a customizable image carousel), have been added to thedroidcorelibrary, enhancing its UI capabilities. - Cross-Platform Component Refactoring: Existing components such as
NeoToastandNetworkImagehave been refactored using Kotlin Multiplatform'sexpect/actualmechanism, providing common APIs with platform-specific implementations for Android and iOS. - Centralized Resource Management: Drawable resources have been moved to
commonMain/composeResourcesand are now accessed via generated resource accessors, ensuring consistent resource availability and usage across all supported platforms. - iOS Application Integration: A new
iosAppmodule has been introduced, complete with necessary Xcode project files and Swift bridging code, to successfully run the shared Compose Multiplatform UI on iOS devices.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Code Review
This pull request primarily focuses on migrating the Droidcore library and its sample app to Kotlin Multiplatform (KMP), enabling support for iOS alongside Android. Key changes include restructuring build configurations, adding an iOS application module, refactoring shared code into commonMain, and implementing platform-specifics using expect/actual. New components like FlipCard, CustomCarousel, and NeoToast have also been introduced or adapted for KMP. The review highlights critical issues in the iOS image loading, potential misconfigurations in build settings, and areas for code cleanup and clarification.
| actual fun NetworkImage( | ||
| url: String, | ||
| contentDescription: String?, | ||
| modifier: Modifier | ||
| ) { | ||
| var imageBitmap by remember { mutableStateOf<ImageBitmap?>(null) } | ||
| var isLoading by remember { mutableStateOf(true) } | ||
| var hasSuccessfullyLoadedOnce by remember(url) { mutableStateOf(false) } | ||
|
|
||
| Text(url) | ||
|
|
||
| } |
There was a problem hiding this comment.
The NetworkImage actual implementation for iOS appears to be incomplete. While it defines the function and includes logic for fetching image data in loadImage(), the composable itself currently only renders Text(url).
The crucial part for converting the fetched UIImage to a ImageBitmap and displaying it (e.g., image.toComposeImageBitmap()) is commented out or missing within the composable body.
This will prevent network images from being displayed on iOS. This needs to be completed for the component to function as expected on the iOS platform.
| excludes += "/META-INF/{AL2.0,LGPL2.1}" | ||
| buildTypes { | ||
| release { | ||
| isMinifyEnabled = false |
There was a problem hiding this comment.
| ENABLE_PREVIEWS = YES; | ||
| FRAMEWORK_SEARCH_PATHS = ( | ||
| "$(inherited)", | ||
| "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)", |
There was a problem hiding this comment.
The FRAMEWORK_SEARCH_PATHS in the Xcode project settings include $(SRCROOT)/../shared/build/xcode-frameworks/... and $(SRCROOT)/../composeApp/build/xcode-frameworks/....
Given the project structure, the KMP module that builds the framework for the iOS app is named app. The shared and composeApp names seem like placeholders from a template and might not correspond to actual module names in this project.
This path should likely be $(SRCROOT)/../app/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME) to correctly locate the framework built by the :app Gradle module. Incorrect paths here can lead to build failures or runtime errors on iOS when trying to link or load the KMP framework.
| android { | ||
| namespace = "id.neotica.droidcore" | ||
| compileSdk = 34 | ||
| compileSdk = 36 |
There was a problem hiding this comment.
The compileSdk has been updated from 34 to 36. While keeping the SDK version up-to-date is good practice, this is a notable jump. Please ensure that the library has been thoroughly tested against this SDK version for any behavioral changes or new compatibility requirements. Also, check for any new lint warnings or errors that might have been introduced.
| //publishing { | ||
| // publications { | ||
| // create<MavenPublication>("bar") { | ||
| // from(components["release"]) | ||
| // groupId = "com.github.laetuz" | ||
| // artifactId = "droidcore-neotica" | ||
| // version = "1.3.0" | ||
| // } | ||
| // publications.withType<MavenPublication> { | ||
| // artifact(javadocJar.get()) | ||
| // | ||
| // pom { | ||
| // name.set("Droidcore") | ||
| // description.set("Droidcore") | ||
| // } | ||
| // } | ||
|
|
||
|
|
||
| // groupId = "id.neotica" | ||
| // artifactId = "droidcore" | ||
| // version = "1.3.1" | ||
| // } | ||
| //} | ||
|
|
||
| //afterEvaluate { | ||
| // publishing.publications.all { | ||
| // this as MavenPublication | ||
| // | ||
| // groupId = "com.github.laetuz" | ||
| // artifactId = "droidcore-neotica" | ||
| // version = "1.3.1" | ||
| // } | ||
|
|
||
| /**og version**/ | ||
| // publishing { | ||
| // publications { | ||
| // create<MavenPublication>("maven") { | ||
| // from(components["release"]) | ||
| // groupId = "com.github.laetuz" | ||
| // artifactId = "droidcore-neotica" | ||
| // version = "1.3.0" | ||
| // } | ||
| // } | ||
| // } | ||
| //} | ||
|
|
||
| //val javadocJar by tasks.registering(Jar::class) { | ||
| // archiveClassifier.set("javadoc") | ||
| //} No newline at end of file |
There was a problem hiding this comment.
| actual fun NeoToast(text: String, appear: MutableState<Boolean>) { | ||
| // val context = AppContext.get().applicationContext | ||
| // LaunchedEffect(Unit) { | ||
| // if (appear.value) { | ||
| // delay(1000) | ||
| // appear.value = false | ||
| // } | ||
| // } | ||
| // if (appear.value) { | ||
| // Toast.makeText(context, text, Toast.LENGTH_SHORT).show() | ||
| // } | ||
|
|
||
| LaunchedEffect(Unit) { | ||
| if (appear.value) { | ||
| delay(1000) | ||
| appear.value = false | ||
| } | ||
| } | ||
|
|
||
| BasicAlertDialog( | ||
| onDismissRequest = { appear.value = false }, | ||
| content = { | ||
| Card { | ||
| Text( | ||
| modifier = Modifier.fillMaxWidth(), | ||
| text = text, | ||
| fontSize = 16.sp, | ||
| textAlign = TextAlign.Center, | ||
| ) | ||
| } | ||
| }, | ||
| ) |
There was a problem hiding this comment.
The NeoToast actual implementation for Android uses BasicAlertDialog. This is an unconventional approach for a component named "Toast", as BasicAlertDialog creates a modal dialog that blocks UI interaction, unlike a standard Android Toast which is non-blocking.
If the intention is to have a non-blocking, short-lived message similar to a native Android Toast, consider using the android.widget.Toast API (perhaps adapting the commented-out code that was present).
If this dialog-like behavior is intentional, it might be clearer to rename the component (e.g., NeoBriefMessageDialog or similar) to better reflect its behavior and avoid confusion with the standard Toast mechanism.
| package id.neotica.droidcore.component.alert.dump | ||
|
|
||
| //import android.content.Context | ||
| //import android.content.Intent | ||
| //import android.net.Uri | ||
| //import androidx.compose.material3.Text | ||
| //import androidx.compose.material3.TextButton | ||
| //import androidx.compose.runtime.Composable | ||
| //import androidx.compose.runtime.MutableState | ||
| //import id.neotica.droidcore.component.alert.NeoAlert | ||
| // | ||
| //@Composable | ||
| //fun PrimaryAlert( | ||
| // openDialog: MutableState<Boolean>, | ||
| // ctx: Context, | ||
| // url: String, | ||
| //) { | ||
| // NeoAlert( | ||
| // openDialog = openDialog, | ||
| // confirmButton = { | ||
| // TextButton( | ||
| // onClick = { | ||
| // val urlIntent = Intent( | ||
| // Intent.ACTION_VIEW, | ||
| // Uri.parse(url) | ||
| // ) | ||
| // ctx.startActivity(urlIntent) | ||
| // } | ||
| // ) { | ||
| // Text("Coba") | ||
| // } | ||
| // }, | ||
| // title = "Fitur dalam pengembangan", | ||
| // desc = "Mohon maaf untuk saat ini fitur yang anda pilih masih dalam tahap pengembangan. Namun anda dapat mencoba fitur ini dengan dengan browser anda." | ||
| // ) | ||
| //} No newline at end of file |
| actual fun NeoToast(text: String, appear: MutableState<Boolean>) { | ||
|
|
||
| LaunchedEffect(Unit) { | ||
| if (appear.value) { | ||
| delay(1000) | ||
| appear.value = false | ||
| } | ||
| } | ||
|
|
||
| BasicAlertDialog( | ||
| onDismissRequest = { appear.value = false }, | ||
| content = { | ||
| Card { | ||
| Text( | ||
| modifier = Modifier.fillMaxWidth(), | ||
| text = text, | ||
| fontSize = 16.sp, | ||
| textAlign = TextAlign.Center, | ||
| ) | ||
| } | ||
| }, | ||
| ) |
There was a problem hiding this comment.
Similar to its Android counterpart, the NeoToast actual implementation for iOS uses BasicAlertDialog. This will result in a modal dialog rather than a non-intrusive, short-lived notification typically associated with a "toast".
If a behavior similar to Android's Toast is desired on iOS (e.g., a small, non-blocking overlay), a custom view or a different presentation approach would be needed. If the current dialog behavior is intended, consider renaming the component for clarity across platforms.
| android.nonTransitiveRClass=true | ||
| android.enableR8.fullMode=false No newline at end of file | ||
| android.enableR8.fullMode=false | ||
| kotlin.native.cacheKind=none No newline at end of file |
There was a problem hiding this comment.
The Kotlin/Native cache kind is set to none (kotlin.native.cacheKind=none). While this can be useful for troubleshooting cache-related issues during development, it typically disables all caching for native compilations, potentially slowing down build times, especially for clean builds or when switching branches frequently.
Consider if this is a temporary setting for debugging or if the performance implications have been evaluated. For regular development and CI builds, static (pre-built caches for dependencies) or other appropriate cache kinds are often preferred for better build performance.
kotlin.native.cacheKind=static # Or remove if default is preferred and 'none' was for debugging
|
/gemini summary |
Summary of ChangesThis pull request introduces a significant architectural change by migrating the Droidcore library to a Kotlin Multiplatform (KMP) foundation. This strategic shift allows for the development of shared UI components that can run natively on both Android and iOS, thereby enhancing code reusability and streamlining cross-platform development efforts. The changes encompass a comprehensive update of the build system, adaptation of existing UI elements for cross-platform compatibility, and the integration of new, platform-agnostic components. Highlights
Changelog
Activity
|
No description provided.