Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/gemini-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Gemini Code Review

on:
pull_request:
types: [opened, synchronize]

jobs:
review:
runs-on: ubuntu-latest
permissions:
pull-requests: write # Allows Gemini to post comments on your PR
contents: read

steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Gemini PR Reviewer
uses: sshnaidm/gemini-code-review-action@v2
with:
gemini-key: ${{ secrets.GEMINI_API_KEY }}
model: "gemini-3.5-flash"
# Adding a custom prompt significantly improves quality
prompt: |
You are an expert Senior Mobile Engineer specializing in Compose Multiplatform (CMP) and Kotlin Multiplatform (KMP) architecture across Android and iOS. Review the provided git diff.

1. Be critical but constructive. Focus heavily on severe logic bugs, security risks, memory leaks, and performance flaws (such as recomposition loops, missing `remember` blocks, or running blocking work inside Composables).
2. Understand KMP Source Sets: Ensure that code in `commonMain` is strictly cross-platform. Flag any accidental imports of Android-specific types (like `android.content.Context`, `Toast`, or Java standard libraries) inside common modules.
3. Idiomatic expect/actual: Verify that `expect`/`actual` patterns are used correctly and placed in the appropriate modules (`commonMain` vs `iosMain`/`androidMain`). Ensure that actual declarations completely satisfy the expected contract.
4. State & Lifecycle Management: Look out for multiplatform State handling. Ensure state hoisting is clean and multiplatform lifecycle components (like CMP-compatible ViewModels or state storage) follow structured concurrency patterns with Coroutines.
5. Cross-Platform UI Pitfalls: Look for issues specific to the CMP UI rendering target (such as missing platform-independent Resource handling like `Res`, unoptimized custom canvas drawing, or breaking layouts on iOS).
6. Do not invent bugs where there are none. If you are unsure about code logic due to missing context or missing file access in the diff, state that clearly instead of guessing or assuming a bug exists.
7. CRITICAL: Do NOT attempt to verify, check, or critique dependency library or Gradle plugin version numbers. You do not have internet access to verify them; completely ignore version updates unless the syntax is explicitly broken.
8. Only comment on lines that require fixes or optimizations. If code looks correct, do not leave a comment.
9. Be highly concise.
46 changes: 46 additions & 0 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.compose.compiler)
}

android {
namespace = "io.github.developrofthings.helloV1"
compileSdk = libs.versions.compileSDK.get().toInt()

defaultConfig {
applicationId = "io.github.developrofthings.helloV1"
minSdk = libs.versions.minSDK.get().toInt()
targetSdk = libs.versions.targetSDK.get().toInt()
versionCode = 1
versionName = "1.0"
}

buildFeatures {
compose = true
}

packaging {
resources {
excludes.add("/META-INF/AL2.0")
excludes.add("/META-INF/LGPL2.1")
}
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11)
}
}
}

dependencies {
implementation(project(":composeApp"))
implementation(libs.androidx.activity.compose)
implementation(libs.core.splashscreen)
implementation(libs.koin.android)
}
46 changes: 46 additions & 0 deletions androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Request legacy Bluetooth permissions on older devices. -->
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30"/>


<uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="31" />

<uses-permission
android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="30" />

<application
android:name=".MainApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.HelloV1.Starting"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:configChanges="uiMode">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ private val lightScrim = Color.argb(0xe6, 0xFF, 0xFF, 0xFF)
* The default dark scrim, as defined by androidx and the platform:
* https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt;l=40-44;drc=27e7d52e8604a080133e8b842db10c89b4482598
*/
private val darkScrim = Color.argb(0x80, 0x1b, 0x1b, 0x1b)
private val darkScrim = Color.argb(0x80, 0x1b, 0x1b, 0x1b)
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ class MainApplication: Application() {
// Make sure the Koin is is initialized
initApp(espContext = ESPContext(this))
}
}
}
2 changes: 0 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.jetbrains.kotlin.android) apply false
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.protobuf) apply false
Expand Down Expand Up @@ -85,4 +84,3 @@ fun Project.configurePublishing(
}
}
}

5 changes: 2 additions & 3 deletions callbacks/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ kotlin {
// Target declarations - add or remove as needed below. These define
// which platforms this KMP module supports.
// See: https://kotlinlang.org/docs/multiplatform-discover-project.html#targets
androidLibrary {
android {
namespace = "io.github.developrofthings.kespl.callbacks"
compileSdk = 36
minSdk = 24

// Configure test that will run on JVM ie "unit test"
withHostTestBuilder {}
withHostTest {}

compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
Expand All @@ -37,7 +37,6 @@ kotlin {

val xcf = XCFramework(xcFrameworkName = xcfName)
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
Expand Down
45 changes: 11 additions & 34 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.android.application)
alias(libs.plugins.android.kotlin.multiplatform.library)
alias(libs.plugins.compose.multiplatform)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.kotlin.serialization)
Expand All @@ -17,15 +17,22 @@ skie {
}

kotlin {
androidTarget {
android {
namespace = "io.github.developrofthings.helloV1.shared"
compileSdk = libs.versions.compileSDK.get().toInt()
minSdk = libs.versions.minSDK.get().toInt()

androidResources {
enable = true
}

compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}

val xcfName = "ComposeAppKit"
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
Expand All @@ -39,15 +46,12 @@ kotlin {
}

sourceSets {
androidMain.dependencies {
implementation(libs.androidx.activity.compose)
implementation(libs.core.splashscreen)
}
commonMain.dependencies {
implementation(libs.compose.runtime)
implementation(libs.compose.foundation)
implementation(libs.compose.material3)
implementation(libs.compose.ui)
implementation(libs.ui.tooling.preview)
implementation(libs.compose.component.resources)
implementation(compose.components.uiToolingPreview)
implementation(libs.androidx.lifecycle.viewmodelCompose)
Expand Down Expand Up @@ -92,33 +96,6 @@ tasks.matching { it.name.startsWith("ksp") && it.name != "kspCommonMainKotlinMet
dependsOn("kspCommonMainKotlinMetadata")
}

android {
namespace = "io.github.developrofthings.helloV1"
compileSdk = libs.versions.compileSDK.get().toInt()

defaultConfig {
namespace = "io.github.developrofthings.helloV1"
minSdk = libs.versions.minSDK.get().toInt()
targetSdk = libs.versions.targetSDK.get().toInt()
versionCode = 1
versionName = "1.0"
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}

tasks.withType<Test> {
useJUnitPlatform()
}
47 changes: 1 addition & 46 deletions composeApp/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,47 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Request legacy Bluetooth permissions on older devices. -->
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30"/>


<uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="31" />

<uses-permission
android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="30" />

<application
android:name=".MainApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.HelloV1.Starting"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:configChanges="uiMode">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import hellov1.composeapp.generated.resources.ic_block
import hellov1.composeapp.generated.resources.ic_bluetooth
import kotlinx.serialization.Serializable
import org.jetbrains.compose.resources.vectorResource
import org.jetbrains.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.Preview

@Serializable
data object Unsupported
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import io.github.developrofthings.kespl.packet.data.displayData.BandArrowIndicator
import org.jetbrains.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun Arrow(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import hellov1.composeapp.generated.resources.ku_band
import hellov1.composeapp.generated.resources.laser_abrv
import hellov1.composeapp.generated.resources.x_band
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.Preview

enum class Bands {
Laser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.Preview

val unlitBarColor: Color = Color(0xFF2F0000)
val litBarColor: Color = Color(0xFFCB0000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import io.github.developrofthings.kespl.packet.data.displayData.SignalStrengthBa
import hellov1.composeapp.generated.resources.Res
import hellov1.composeapp.generated.resources.strength
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun BarGraph(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import hellov1.composeapp.generated.resources.valentine_1
import hellov1.composeapp.generated.resources.volume_controls
import org.jetbrains.compose.resources.stringArrayResource
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun ESPCommandPanel(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import hellov1.composeapp.generated.resources.override_thumbwheel
import hellov1.composeapp.generated.resources.request_savvy_status
import hellov1.composeapp.generated.resources.savvy
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun SAVVYPanel(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import io.github.developrofthings.kespl.utilities.extensions.primitive.get
import org.jetbrains.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun SevenSegment(
Expand Down
Loading
Loading