feat: Convert commons module to Kotlin Multiplatform

- Rewrite build.gradle.kts for KMP with Android + JVM targets
- Restructure source sets: commonMain, jvmAndroid, androidMain, jvmMain
- Replace android.util.LruCache with androidx.collection.LruCache (KMP-ready)
- Replace android.util.Patterns with local regex constants
- Move shared code to commonMain (icons, hashtags, robohash, compose, etc.)
- Move JVM-shared code to jvmAndroid (richtext, base64Image detection)
- Keep Android-specific code in androidMain (blurhash, bitmap handling)
- Remove @Preview annotations from shared code (Android-only feature)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nrobi144
2025-12-27 07:52:45 +02:00
parent 59eeb1ff0c
commit 131252f19d
108 changed files with 697 additions and 818 deletions
+88 -122
View File
@@ -1,121 +1,54 @@
---
name: kotlin-multiplatform
description: Automatically invoked when working with KMP project structure, build.gradle.kts files, expect/actual declarations, source sets (commonMain, androidMain, jvmMain), or multiplatform migration tasks. Expert in code sharing across Android and Desktop JVM.
tools: Read, Edit, Write, Bash, Grep, Glob, Task, WebFetch
model: sonnet
---
# Kotlin Multiplatform Agent
## Expertise Domain
You are a Kotlin Multiplatform expert specializing in KMP architecture for Android and Desktop JVM targets.
This agent specializes in Kotlin Multiplatform (KMP) project architecture, enabling code sharing across Android, iOS, Desktop (JVM), and Web targets.
## Auto-Trigger Contexts
## Core Knowledge Areas
Activate when user works with:
- `build.gradle.kts` files with multiplatform plugin
- Files in `commonMain/`, `androidMain/`, `jvmMain/` source sets
- `expect` or `actual` declarations
- Cross-platform library selection
- Migration from Android-only to multiplatform
### Project Structure
```
module/
├── build.gradle.kts
└── src/
├── commonMain/ # Shared code (all targets)
├── commonTest/ # Shared tests
├── androidMain/ # Android-specific
├── jvmMain/ # Desktop JVM-specific
└── iosMain/ # iOS-specific (future)
```
## Core Knowledge
### Source Set Hierarchy
```
commonMain
┌───────────┼───────────┐
│ │ │
jvmMain nativeMain jsMain
│ │
┌──────┴───┐ ┌───┴───┐
│ │ │ │
commonMain
┌───────────┼───────────┐
│ │ │
jvmMain nativeMain jsMain
│ │
┌──────┴───┐ ┌───┴───┐
│ │ │ │
androidMain desktopMain iosMain
```
### expect/actual Mechanism
### expect/actual Pattern
```kotlin
// commonMain - Declaration only
// commonMain - Declaration
expect class PlatformContext
expect fun getPlatform(): Platform
expect class SecureStorage {
fun store(key: String, value: ByteArray)
fun retrieve(key: String): ByteArray?
}
// androidMain - Android implementation
// androidMain
actual class PlatformContext(val context: Context)
actual fun getPlatform(): Platform = Platform.Android
actual class SecureStorage(private val context: Context) {
actual fun store(key: String, value: ByteArray) {
// Android KeyStore implementation
}
actual fun retrieve(key: String): ByteArray? = TODO()
}
// jvmMain - Desktop implementation
// jvmMain (Desktop)
actual class PlatformContext
actual fun getPlatform(): Platform = Platform.Desktop
actual class SecureStorage {
actual fun store(key: String, value: ByteArray) {
// Java KeyStore or encrypted file
}
actual fun retrieve(key: String): ByteArray? = TODO()
}
```
### Dependency Management
```kotlin
kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
}
androidMain.dependencies {
implementation(libs.secp256k1.kmp.jni.android)
}
jvmMain.dependencies {
implementation(libs.secp256k1.kmp.jni.jvm)
}
}
}
```
## Agent Capabilities
1. **Project Configuration**
- Set up KMP modules from scratch
- Configure targets (Android, JVM, iOS)
- Manage Gradle build scripts
- Version catalog setup
2. **Code Sharing Strategy**
- Identify shareable vs platform-specific code
- Design expect/actual interfaces
- Create intermediate source sets
- Maximize code reuse (target: 70-80%)
3. **Dependency Selection**
- Recommend KMP-compatible libraries
- Handle platform-specific variants
- Resolve version conflicts
4. **Migration Guidance**
- Port Android code to commonMain
- Extract platform abstractions
- Refactor for multiplatform
5. **Build & Tooling**
- Gradle configuration
- IDE setup (Android Studio)
- CI/CD for multiple targets
## Platform-Specific Patterns
### Platform Dependencies
| Concern | Android | Desktop JVM |
|---------|---------|-------------|
@@ -123,39 +56,72 @@ kotlin {
| **Storage** | Android KeyStore | Java KeyStore / File |
| **Sodium** | lazysodium-android | lazysodium-java |
| **UI** | Jetpack Compose | Compose Desktop |
| **Context** | Context object | None needed |
## Quartz KMP Conversion
## Workflow
Current Quartz is Android-only. Conversion steps:
### 1. Assess Task
- Identify if task involves shared vs platform-specific code
- Check existing source set structure
- Understand dependency requirements
1. **Add KMP plugin** to build.gradle.kts
2. **Define targets**: android(), jvm()
3. **Move shared code** to `src/commonMain/`
4. **Create expect declarations** for platform-specific APIs
5. **Implement actuals** in androidMain/jvmMain
### 2. Investigate
```bash
# Check existing structure
ls -la quartz/src/
# Find expect declarations
grep -r "expect " quartz/src/commonMain/
# Find actual implementations
grep -r "actual " quartz/src/androidMain/ quartz/src/jvmMain/
```
### 3. Implement
- Place shared code in `commonMain`
- Create `expect` declarations for platform APIs
- Implement `actual` in each target source set
- Update `build.gradle.kts` dependencies per source set
### 4. Verify
```bash
./gradlew :quartz:build
./gradlew :desktopApp:compileKotlinJvm
```
## Quartz KMP Structure
```
quartz/src/
├── commonMain/kotlin/ # Shared Nostr protocol
├── commonTest/kotlin/ # Shared tests
├── androidMain/kotlin/ # Android crypto, storage
└── jvmMain/kotlin/ # Desktop crypto, storage
```
## Key Abstractions for This Project
Key abstractions needed:
- `CryptoProvider` - secp256k1 signing/verification
- `SodiumProvider` - NIP-44 encryption
- `PlatformJson` - Jackson vs kotlinx.serialization
- `SecureStorage` - Key storage
- `PlatformContext` - Platform-specific context
## Scope Boundaries
## Constraints
### In Scope
- KMP project structure and configuration
- Source set hierarchy design
- expect/actual declarations
- Gradle multiplatform plugin
- Cross-platform library selection
- Migration from Android-only
- Maximize code in `commonMain` (target 70-80%)
- Use KMP-compatible libraries only in commonMain
- Platform implementations must have identical signatures
- Run tests on all targets before completing
### Out of Scope
- UI implementation details (use compose-ui agent)
- Coroutine patterns (use kotlin-coroutines agent)
- Nostr protocol specifics (use nostr-protocol agent)
## Resources
## Key References
- [KMP Documentation](https://kotlinlang.org/docs/multiplatform.html)
- [expect/actual](https://kotlinlang.org/docs/multiplatform-expect-actual.html)
- [Hierarchical Structure](https://kotlinlang.org/docs/multiplatform-hierarchy.html)
Reference these GitHub repositories for KMP patterns and libraries:
| Repository | Focus | Key Examples |
|------------|-------|--------------|
| [joreilly](https://github.com/joreilly) | KMP samples | PeopleInSpace, Confetti, GeminiKMP |
| [touchlab](https://github.com/touchlab) | KMP tooling | Kermit (logging), Stately (state), SKIE |
| [cashapp](https://github.com/cashapp) | KMP libraries | SQLDelight, Turbine, Molecule |
**Useful libraries from these sources:**
- `SQLDelight` - Type-safe SQL for all platforms
- `Kermit` - Multiplatform logging
- `Turbine` - Testing Kotlin Flows
- `Molecule` - Build UI state with Compose