diff --git a/.github/actions/java/action.yml b/.github/actions/java/action.yml new file mode 100644 index 0000000..f2abf45 --- /dev/null +++ b/.github/actions/java/action.yml @@ -0,0 +1,13 @@ +name: "Java setup" +description: "Setup Java" + +runs: + using: "composite" + steps: + - uses: actions/checkout@v4 + - name: set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: "17" + distribution: "temurin" + cache: gradle \ No newline at end of file diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 302c235..d951c5c 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -14,11 +14,9 @@ jobs: - name: Check out code uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - distribution: "temurin" - java-version: "17" + - uses: actions/checkout@v4 + - name: Setup Java + uses: ./.github/actions/java - name: Set up Android SDK uses: android-actions/setup-android@v2 @@ -40,11 +38,9 @@ jobs: - name: Check out code uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - distribution: "temurin" - java-version: "17" + - uses: actions/checkout@v4 + - name: Setup Java + uses: ./.github/actions/java - name: Run Unit Tests run: ./gradlew testDebugUnitTest --no-daemon diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7ed3c70..9387077 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -25,7 +25,11 @@ jobs: echo "ORG_GRADLE_PROJECT_signingInMemoryKey: $ORG_GRADLE_PROJECT_signingInMemoryKey" echo "ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: $ORG_GRADLE_PROJECT_signingInMemoryKeyPassword" echo "ORG_GRADLE_PROJECT_signingInMemoryKeyId: $ORG_GRADLE_PROJECT_signingInMemoryKeyId" - ./gradlew publish --no-daemon + ./gradlew \ + :craftd-core:publishAllPublicationsToMavenCentralRepository \ + :craftd-compose:publishAllPublicationsToMavenCentralRepository \ + :craftd-xml:publish \ + --no-daemon env: ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.ORG_GRADLE_PROJECT_MAVENCENTRALUSERNAME }} ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.ORG_GRADLE_PROJECT_MAVENCENTRALPASSWORD }} @@ -34,6 +38,27 @@ jobs: ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.ORG_GRADLE_PROJECT_SIGNINGINMEMORYKEY }} working-directory: android_kmp + tag: + name: Update tags per module + runs-on: ubuntu-latest + needs: publish + + strategy: + matrix: + module: + - name: craftd-core + prefix: kmp + - name: craftd-compose + prefix: kmp + - name: craftd-xml + prefix: android + + steps: + - name: Check out code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Setup Ruby uses: ruby/setup-ruby@v1 with: @@ -47,6 +72,4 @@ jobs: bundle install --jobs 4 --retry 3 - name: Update tag - run: bundle exec fastlane update_tag - env: - PREFIX: "android" + run: PREFIX=${{ matrix.module.prefix }} bundle exec fastlane update_tag \ No newline at end of file diff --git a/README.md b/README.md index e64cebf..6e762c1 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,13 @@ Take a look at [CraftD: Server Driven UI for All Platforms](https://medium.com/c ## Features ### 🔗 Compatibility -| Tech | Support | -|---------------------------------|:--------------------:| -| View System - Android | ✅ **Supported** | -| Jetpack Compose - Android | ✅ **Supported** | -| Widget - Flutter | ✅ **Supported** | -| SwiftUi - iOS | ✅ **Supported** | -| Jetpack Compose - Multiplatform | ⚒ **In Progress** | +| Tech | Support | +|---------------------------------|:-------------------:| +| View System - Android | ✅ **Supported** | +| Jetpack Compose - Android | ✅ **Supported** | +| Widget - Flutter | ✅ **Supported** | +| SwiftUi - iOS | ✅ **Supported** | +| Jetpack Compose - Multiplatform | ✅ **Supported** | ### Components that already exist in the library @@ -34,65 +34,13 @@ Take a look at [CraftD: Server Driven UI for All Platforms](https://medium.com/c | Text | X | X | X | X | | CheckBox | X | - | - | X | -### Create your custom component( android compose example ) - -```kotlin -@JsonIgnoreProperties(ignoreUnknown = true) -@Immutable -@Stable -data class CheckBoxProperties( - @JsonProperty("text") val text: String? = null, - ... rest of your properties -) - -``` - -#### Add your Component json object in Dymanic.json -```json -{ - "key": "CraftDCheckBox", - "value": { - ... place your properties - } -} - -``` - -#### Create your Component -```kotlin -@Composable -fun CraftDCheckBox( - checkboxProperties: CheckBoxProperties, - modifier: Modifier = Modifier, - onChecked: (Boolean) -> Unit -) { - ... place your code -} -``` - -#### Create your Component Builder -```kotlin -class CraftDCheckBoxBuilder( - override val key: String = CraftDComponentKey.CHECK_BOX_COMPONENT.key -) : - CraftDBuilder { - @Composable - override fun craft(model: SimpleProperties, listener: CraftDViewListener) { - val checkBoxProperties = model.value.convertToVO() - CraftDCheckBox(checkBoxProperties) { - checkBoxProperties.actionProperties?.let { listener.invoke(it) } - } - } -} -``` - More details check our [documentation](https://codandotv.gitbook.io/craftd) ### Samples -| [Android Compose](https://github.com/CodandoTV/CraftD/tree/main/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose) | [Android View System](https://github.com/CodandoTV/CraftD/tree/main/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml) | [iOS SwiftUI](https://github.com/CodandoTV/CraftD/tree/main/ios/sample/CraftDSample) | [Flutter](https://github.com/CodandoTV/CraftD/tree/main/flutter/sample/lib) | -|----------|----------|----------|----------| -| | | | | +| [Android Compose / Compose MultiPlatform](https://github.com/CodandoTV/CraftD/tree/main/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose) | [Android View System](https://github.com/CodandoTV/CraftD/tree/main/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml) | [iOS SwiftUI](https://github.com/CodandoTV/CraftD/tree/main/ios/sample/CraftDSample) | [Flutter](https://github.com/CodandoTV/CraftD/tree/main/flutter/sample/lib) | +|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|----------|----------| +| | | | | ### Credits diff --git a/android_kmp/.gitignore b/android_kmp/.gitignore new file mode 100644 index 0000000..042103a --- /dev/null +++ b/android_kmp/.gitignore @@ -0,0 +1,139 @@ +# ========================================= +# Kotlin Multiplatform / Compose Multiplatform +# ========================================= + +# Build system +/build/ +.gradle/ +local.properties +!gradle/wrapper/gradle-wrapper.jar +.gradle-cache/ +.gradle/ +.gradle.kts.cached +.gradle/configuration-cache/ +.kotlinc/ +.kotlin + +# IDEs +.idea/ +*.iml +*.ipr +*.iws +.vscode/ +*.sw? +*.swo +*.orig + +# Kotlin/Java +out/ +bin/ +classes/ +*.class +*.log +*.tmp +*.lock +*.hprof + +# Compose Multiplatform generated resources +composeApp/build/ +composeApp/.kotlin/ +composeApp/.compose-cache/ +composeApp/.cache/ +composeApp/compose-resources/ + +# KMP common artifacts +common/build/ +shared/build/ +**/build/ +**/.kotlin/ +**/.kotlin-js-store/ +**/.gradle/ +**/.idea_modules/ + +# Android +captures/ +*.apk +*.ap_ +*.aab +*.dex +*.class +*.keystore +*.jks +*.so +*.aar +*.iml +**/local.properties +**/generated/ +**/outputs/ +**/reports/ +**/release/ +**/debug/ + +# iOS +xcuserdata/ +DerivedData/ +build/XCFrameworks/ +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +*.xcworkspace/ +!*.xcworkspace/contents.xcworkspacedata +Pods/ +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 +*.xcuserstate +.DS_Store + +# Native (K/N) +.konan/ +**/bin/ +**/obj/ +**/native/ + +# Packaging / Distribution +*.zip +*.tar +*.tar.gz +*.tgz +*.jar +*.war +*.ear +*.klib +*.xcframework +*.framework + +# Temporary files +*.tmp +*.bak +*.orig +*.swp +*.swo +*.rej +*.sublime-workspace +*.sublime-project + +# Environment / Credentials +.env +.env.* +*.key +*.pem +*.p12 +*.keystore +*.jks +secrets.properties +signing.properties + +# OS files +.DS_Store +Thumbs.db +ehthumbs.db +Desktop.ini + +# ========================================= +# Optional: ignore intermediate build logic +# ========================================= +build-logic/.gradle/ +build-logic/build/ +gradle.properties diff --git a/android_kmp/KMP-Sample/.gitignore b/android_kmp/KMP-Sample/.gitignore new file mode 100644 index 0000000..adfa9bf --- /dev/null +++ b/android_kmp/KMP-Sample/.gitignore @@ -0,0 +1,19 @@ +*.iml +.kotlin +.gradle +**/build/ +xcuserdata +!src/**/build/ +local.properties +.idea +.DS_Store +captures +.externalNativeBuild +.cxx +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcodeproj/project.xcworkspace/ +!*.xcworkspace/contents.xcworkspacedata +**/xcshareddata/WorkspaceSettings.xcsettings +node_modules/ diff --git a/android_kmp/KMP-Sample/README.md b/android_kmp/KMP-Sample/README.md new file mode 100644 index 0000000..7e7d049 --- /dev/null +++ b/android_kmp/KMP-Sample/README.md @@ -0,0 +1,35 @@ +This is a Kotlin Multiplatform project targeting Android, iOS. + +* [/composeApp](./composeApp/src) is for code that will be shared across your Compose Multiplatform applications. + It contains several subfolders: + - [commonMain](./composeApp/src/commonMain/kotlin) is for code that’s common for all targets. + - Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name. + For example, if you want to use Apple’s CoreCrypto for the iOS part of your Kotlin app, + the [iosMain](./composeApp/src/iosMain/kotlin) folder would be the right place for such calls. + Similarly, if you want to edit the Desktop (JVM) specific part, the [jvmMain](./composeApp/src/jvmMain/kotlin) + folder is the appropriate location. + +* [/iosApp](./iosApp/iosApp) contains iOS applications. Even if you’re sharing your UI with Compose Multiplatform, + you need this entry point for your iOS app. This is also where you should add SwiftUI code for your project. + +### Build and Run Android Application + +To build and run the development version of the Android app, use the run configuration from the run widget +in your IDE’s toolbar or build it directly from the terminal: +- on macOS/Linux + ```shell + ./gradlew :composeApp:assembleDebug + ``` +- on Windows + ```shell + .\gradlew.bat :composeApp:assembleDebug + ``` + +### Build and Run iOS Application + +To build and run the development version of the iOS app, use the run configuration from the run widget +in your IDE’s toolbar or open the [/iosApp](./iosApp) directory in Xcode and run it from there. + +--- + +Learn more about [Kotlin Multiplatform](https://www.jetbrains.com/help/kotlin-multiplatform-dev/get-started.html)
 \ No newline at end of file diff --git a/android_kmp/KMP-Sample/build.gradle.kts b/android_kmp/KMP-Sample/build.gradle.kts new file mode 100644 index 0000000..430c60f --- /dev/null +++ b/android_kmp/KMP-Sample/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + alias(libs.plugins.androidApplication) apply false + alias(libs.plugins.androidLibrary) apply false + alias(libs.plugins.composeMultiplatform) apply false + alias(libs.plugins.composeCompiler) apply false + alias(libs.plugins.kotlinMultiplatform) apply false +} \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/build.gradle.kts b/android_kmp/KMP-Sample/composeApp/build.gradle.kts new file mode 100644 index 0000000..935ba66 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/build.gradle.kts @@ -0,0 +1,84 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidApplication) + alias(libs.plugins.composeMultiplatform) + alias(libs.plugins.composeCompiler) + id("org.jetbrains.kotlin.plugin.serialization") version "2.2.21" +} + +kotlin { + androidTarget { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + } + } + + listOf( + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "ComposeApp" + isStatic = true + } + } + + sourceSets { + androidMain.dependencies { + implementation(compose.preview) + implementation(libs.androidx.activity.compose) + } + commonMain.dependencies { + implementation(libs.craftd.compose) +// implementation(libs.craftd.core) + implementation(compose.runtime) + implementation(libs.kotlinx.coroutines.core) + implementation(libs.kotlinx.serialization.json) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.ui) + implementation(compose.components.uiToolingPreview) + implementation(libs.androidx.lifecycle.viewmodelCompose) + implementation(libs.androidx.lifecycle.runtimeCompose) + implementation(libs.kotlinx.collections.immutable) + implementation(compose.components.resources) + } + commonTest.dependencies { + implementation(libs.kotlin.test) + } + } +} + +android { + namespace = "org.example.project" + compileSdk = libs.versions.android.compileSdk.get().toInt() + + defaultConfig { + applicationId = "org.example.project" + minSdk = libs.versions.android.minSdk.get().toInt() + targetSdk = libs.versions.android.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_17 + targetCompatibility = JavaVersion.VERSION_17 + } +} + +dependencies { + debugImplementation(compose.uiTooling) +} + diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/AndroidManifest.xml b/android_kmp/KMP-Sample/composeApp/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000..26403a7 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/androidMain/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/kotlin/org/example/project/MainActivity.kt b/android_kmp/KMP-Sample/composeApp/src/androidMain/kotlin/org/example/project/MainActivity.kt new file mode 100644 index 0000000..e2bb0ed --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/androidMain/kotlin/org/example/project/MainActivity.kt @@ -0,0 +1,25 @@ +package org.example.project + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() + super.onCreate(savedInstanceState) + + setContent { + App() + } + } +} + +@Preview +@Composable +fun AppAndroidPreview() { + App() +} \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/kotlin/org/example/project/Platform.android.kt b/android_kmp/KMP-Sample/composeApp/src/androidMain/kotlin/org/example/project/Platform.android.kt new file mode 100644 index 0000000..63d6f9f --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/androidMain/kotlin/org/example/project/Platform.android.kt @@ -0,0 +1,9 @@ +package org.example.project + +import android.os.Build + +class AndroidPlatform : Platform { + override val name: String = "Android ${Build.VERSION.SDK_INT}" +} + +actual fun getPlatform(): Platform = AndroidPlatform() \ No newline at end of file diff --git a/android_kmp/app-sample/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to android_kmp/KMP-Sample/composeApp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/drawable/ic_launcher_background.xml b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..e93e11a --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/android_kmp/app-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a571e60 Binary files /dev/null and b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..61da551 Binary files /dev/null and b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..c41dd28 Binary files /dev/null and b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..db5080a Binary files /dev/null and b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6dba46d Binary files /dev/null and b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..da31a87 Binary files /dev/null and b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..15ac681 Binary files /dev/null and b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..b216f2d Binary files /dev/null and b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..f25a419 Binary files /dev/null and b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..e96783c Binary files /dev/null and b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/android_kmp/KMP-Sample/composeApp/src/androidMain/res/values/strings.xml b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/values/strings.xml new file mode 100644 index 0000000..84cb5ca --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/androidMain/res/values/strings.xml @@ -0,0 +1,3 @@ + + KMP-Sample + \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/commonMain/composeResources/drawable/compose-multiplatform.xml b/android_kmp/KMP-Sample/composeApp/src/commonMain/composeResources/drawable/compose-multiplatform.xml new file mode 100644 index 0000000..1ffc948 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/commonMain/composeResources/drawable/compose-multiplatform.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/commonMain/composeResources/files/dynamic.json b/android_kmp/KMP-Sample/composeApp/src/commonMain/composeResources/files/dynamic.json new file mode 100644 index 0000000..5997a18 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/commonMain/composeResources/files/dynamic.json @@ -0,0 +1,371 @@ +[ + { + "key": "CraftDTextView", + "value": { + "text": "KMP Works", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "textSize": "20", + "textColorHex": "#FF0000", + "align": "CENTER", + "textStyle": "BOLD", + "textAllCaps": true, + "textHtml": "

Este Ă© um texto em HTML

Isso Ă© itĂĄlico

" + } + }, + { + "key": "CraftDButton", + "value": { + "text": "Some Action :)", + "align": "CENTER", + "textAlign": "CENTER", + "textAllCaps": true, + "textSize": "20", + "textColorHex": "#FFFFFF", + "backgroundHex": "#2fa003", + "actionProperties": { + "deeplink": "CraftDview://any", + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + }, + { + "key": "CraftDCheckBox", + "value": { + "text": "Mark here ", + "align": "RIGHT", + "textAlign": "CENTER", + "hasItRightText": false, + "enable": true, + "style": { + "checkedColorHex": "#FF0000", + "uncheckedColorHex": " #808080" + }, + "actionProperties": { + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + }, + { + "key": "MySampleButton", + "value": { + "text": "MySampleButton", + "align": "RIGHT", + "textAlign": "CENTER", + "textAllCaps": true, + "textSize": "20", + "textColorHex": "#FFFFFF", + "backgroundHex": "#2fa003", + "actionProperties": { + "deeplink": "CraftDview://any", + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Knife", + "backgroundHex": "#9A71F6", + "textSize": "30", + "textColorHex": "#000000" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "textSize": "20", + "textColorHex": "#FF0000", + "align": "CENTER", + "textStyle": "BOLD", + "textAllCaps": true, + "textHtml": "

Este Ă© um texto em HTML

Isso Ă© itĂĄlico

" + } + }, + { + "key": "CraftDButton", + "value": { + "text": "Some Action :)", + "align": "RIGHT", + "textAlign": "CENTER", + "textAllCaps": true, + "textSize": "20", + "textColorHex": "#FFFFFF", + "backgroundHex": "#2fa003", + "actionProperties": { + "deeplink": "CraftDview://any", + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Knife", + "backgroundHex": "#9A71F6", + "textSize": "30", + "textColorHex": "#000000" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "textSize": "20", + "textColorHex": "#FF0000", + "align": "CENTER", + "textStyle": "BOLD", + "textAllCaps": true, + "textHtml": "

Este Ă© um texto em HTML

Isso Ă© itĂĄlico

" + } + }, + { + "key": "CraftDButton", + "value": { + "text": "Some Action :)", + "align": "RIGHT", + "textAlign": "CENTER", + "fillMaxSize": false, + "textAllCaps": true, + "textSize": "20", + "textColorHex": "#FFFFFF", + "backgroundHex": "#2fa003", + "actionProperties": { + "deeplink": "CraftDview://any", + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Knife", + "backgroundHex": "#9A71F6", + "textSize": "30", + "textColorHex": "#000000" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "textSize": "20", + "textColorHex": "#FF0000", + "align": "CENTER", + "textStyle": "BOLD", + "textAllCaps": true, + "textHtml": "

Este Ă© um texto em HTML

Isso Ă© itĂĄlico

" + } + }, + { + "key": "CraftDButton", + "value": { + "text": "Some Action :)", + "align": "RIGHT", + "textAlign": "CENTER", + "textAllCaps": true, + "textSize": "20", + "textColorHex": "#FFFFFF", + "backgroundHex": "#2fa003", + "actionProperties": { + "deeplink": "deeplink://any", + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + } +] \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/App.kt b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/App.kt new file mode 100644 index 0000000..4ba13a0 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/App.kt @@ -0,0 +1,14 @@ +package org.example.project + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import org.example.project.presentation.compose.InitialScreen +import org.jetbrains.compose.ui.tooling.preview.Preview + +@Composable +@Preview +fun App() { + MaterialTheme { + InitialScreen() + } +} \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/Greeting.kt b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/Greeting.kt new file mode 100644 index 0000000..d49d319 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/Greeting.kt @@ -0,0 +1,9 @@ +package org.example.project + +class Greeting { + private val platform = getPlatform() + + fun greet(): String { + return "Hello, ${platform.name}!" + } +} \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/Platform.kt b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/Platform.kt new file mode 100644 index 0000000..6018b28 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/Platform.kt @@ -0,0 +1,7 @@ +package org.example.project + +interface Platform { + val name: String +} + +expect fun getPlatform(): Platform \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/data/SampleCraftDRepository.kt b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/data/SampleCraftDRepository.kt new file mode 100644 index 0000000..20c7f6b --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/data/SampleCraftDRepository.kt @@ -0,0 +1,24 @@ +package org.example.project.data + +import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties +import kmp_sample.composeapp.generated.resources.Res +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.serialization.json.Json + +interface SampleCraftDRepository { + suspend fun getDynamic(): Flow> +} + +class SampleCraftDRepositoryImpl() : SampleCraftDRepository { + + override suspend fun getDynamic(): Flow> = flow { + val jsonString = Res.readBytes("files/dynamic.json") + .decodeToString() + + val list = Json { ignoreUnknownKeys = true } + .decodeFromString>(jsonString) + + emit(list) + } +} diff --git a/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/InitialScreen.kt b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/InitialScreen.kt new file mode 100644 index 0000000..5949615 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/InitialScreen.kt @@ -0,0 +1,35 @@ +package org.example.project.presentation.compose + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import org.example.project.presentation.compose.customview.MySampleButtonComposeBuilder +import com.github.codandotv.craftd.compose.builder.CraftDBuilderManager +import com.github.codandotv.craftd.compose.ui.CraftDynamic +import org.example.project.data.SampleCraftDRepositoryImpl + +@Composable +fun InitialScreen( + vm: SampleCraftDComposeViewModel = SampleCraftDComposeViewModel(SampleCraftDRepositoryImpl()) +) { + val properties by vm.properties.collectAsState() + val craftdBuilderManager = remember { + CraftDBuilderManager().add( + MySampleButtonComposeBuilder(), + ) + } + LaunchedEffect(Unit) { + vm.loadProperties() + } + + CraftDynamic( + properties = properties, + craftDBuilderManager = craftdBuilderManager + ) { + println( + ">>>> category ${it.analytics?.category} -" + " action ${it.analytics?.action} -" + " label ${it.analytics?.label} -" + " deeplink ${it.deeplink}" + ) + } +} \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/SampleCraftDComposeViewModel.kt b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/SampleCraftDComposeViewModel.kt new file mode 100644 index 0000000..e71c7fd --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/SampleCraftDComposeViewModel.kt @@ -0,0 +1,33 @@ +package org.example.project.presentation.compose + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import org.example.project.data.SampleCraftDRepository + +class SampleCraftDComposeViewModel(private val repository: SampleCraftDRepository) : ViewModel() { + private val _properties = MutableStateFlow>(persistentListOf()) + val properties = _properties.stateIn( + viewModelScope, SharingStarted.Eagerly, + initialValue = _properties.value + ) + + fun loadProperties() { + viewModelScope.launch { + repository.getDynamic().collectLatest { newList -> + _properties.update { + newList.toImmutableList() + } + } + } + } +} \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButton.kt b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButton.kt new file mode 100644 index 0000000..6cde5a7 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButton.kt @@ -0,0 +1,32 @@ +package org.example.project.presentation.compose.customview + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.github.codandotv.craftd.androidcore.data.model.button.ButtonProperties +import com.github.codandotv.craftd.compose.extensions.toArrangementCompose + +@Composable +fun MySampleButton( + buttonProperties: ButtonProperties, + modifier: Modifier = Modifier, + onClick: () -> Unit, +) { + Row( + horizontalArrangement = buttonProperties.align.toArrangementCompose(), + modifier = Modifier.fillMaxWidth() + ) { + Button( + onClick = onClick, + colors = ButtonDefaults.buttonColors(containerColor = Color.Magenta), + modifier = modifier, + ) { + Text(buttonProperties.text ?: "empty") + } + } +} \ No newline at end of file diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/customview/MySampleButtonComposeBuilder.kt b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButtonComposeBuilder.kt similarity index 60% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/customview/MySampleButtonComposeBuilder.kt rename to android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButtonComposeBuilder.kt index 36c067b..be47b57 100644 --- a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/customview/MySampleButtonComposeBuilder.kt +++ b/android_kmp/KMP-Sample/composeApp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButtonComposeBuilder.kt @@ -1,7 +1,7 @@ -package com.github.codandotv.craftd.app_sample.presentation.compose.customview +package org.example.project.presentation.compose.customview import androidx.compose.runtime.Composable -import com.github.codandotv.craftd.androidcore.data.convertToVO +import com.github.codandotv.craftd.androidcore.data.convertToElement import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties import com.github.codandotv.craftd.androidcore.data.model.button.ButtonProperties import com.github.codandotv.craftd.androidcore.presentation.CraftDViewListener @@ -10,9 +10,11 @@ import com.github.codandotv.craftd.compose.builder.CraftDBuilder class MySampleButtonComposeBuilder(override val key: String = "MySampleButton") : CraftDBuilder { @Composable override fun craft(model: SimpleProperties, listener: CraftDViewListener) { - val buttonProperties = model.value.convertToVO() - MySampleButton(buttonProperties) { - buttonProperties.actionProperties?.let { listener.invoke(it) } + val buttonProperties = model.value.convertToElement() + buttonProperties?.let { + MySampleButton(it) { + buttonProperties.actionProperties?.let { listener.invoke(it) } + } } } } \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/commonTest/kotlin/org/example/project/ComposeAppCommonTest.kt b/android_kmp/KMP-Sample/composeApp/src/commonTest/kotlin/org/example/project/ComposeAppCommonTest.kt new file mode 100644 index 0000000..8e0efeb --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/commonTest/kotlin/org/example/project/ComposeAppCommonTest.kt @@ -0,0 +1,12 @@ +package org.example.project + +import kotlin.test.Test +import kotlin.test.assertEquals + +class ComposeAppCommonTest { + + @Test + fun example() { + assertEquals(3, 1 + 2) + } +} \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/iosMain/kotlin/org/example/project/MainViewController.kt b/android_kmp/KMP-Sample/composeApp/src/iosMain/kotlin/org/example/project/MainViewController.kt new file mode 100644 index 0000000..f235c15 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/iosMain/kotlin/org/example/project/MainViewController.kt @@ -0,0 +1,5 @@ +package org.example.project + +import androidx.compose.ui.window.ComposeUIViewController + +fun MainViewController() = ComposeUIViewController { App() } \ No newline at end of file diff --git a/android_kmp/KMP-Sample/composeApp/src/iosMain/kotlin/org/example/project/Platform.ios.kt b/android_kmp/KMP-Sample/composeApp/src/iosMain/kotlin/org/example/project/Platform.ios.kt new file mode 100644 index 0000000..aea8f33 --- /dev/null +++ b/android_kmp/KMP-Sample/composeApp/src/iosMain/kotlin/org/example/project/Platform.ios.kt @@ -0,0 +1,9 @@ +package org.example.project + +import platform.UIKit.UIDevice + +class IOSPlatform: Platform { + override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion +} + +actual fun getPlatform(): Platform = IOSPlatform() \ No newline at end of file diff --git a/android_kmp/KMP-Sample/gradle.properties b/android_kmp/KMP-Sample/gradle.properties new file mode 100644 index 0000000..6f8e6ea --- /dev/null +++ b/android_kmp/KMP-Sample/gradle.properties @@ -0,0 +1,12 @@ +#Kotlin +kotlin.code.style=official +kotlin.daemon.jvmargs=-Xmx3072M + +#Gradle +org.gradle.jvmargs=-Xmx4096M -Dfile.encoding=UTF-8 +org.gradle.configuration-cache=true +org.gradle.caching=true + +#Android +android.nonTransitiveRClass=true +android.useAndroidX=true \ No newline at end of file diff --git a/android_kmp/KMP-Sample/gradle/libs.versions.toml b/android_kmp/KMP-Sample/gradle/libs.versions.toml new file mode 100644 index 0000000..a0f8bbd --- /dev/null +++ b/android_kmp/KMP-Sample/gradle/libs.versions.toml @@ -0,0 +1,42 @@ +[versions] +agp = "8.10.0" +android-compileSdk = "36" +android-minSdk = "24" +android-targetSdk = "36" +androidx-activity = "1.11.0" +androidx-appcompat = "1.7.1" +androidx-core = "1.17.0" +androidx-espresso = "3.7.0" +androidx-lifecycle = "2.9.4" +androidx-testExt = "1.3.0" +composeMultiplatform = "1.9.0" +craftdCompose = "1.1.0" +junit = "4.13.2" +kotlin = "2.2.21" +kotlinxCoroutinesCore = "1.10.2" +kotlinxSerializationJson = "1.9.0" +kotlinx-collections-immutable = "0.4.0" + +[libraries] +craftd-compose = { module = "io.github.codandotv:craftd-compose", version.ref = "craftdCompose" } +craftd-core = { module = "io.github.codandotv:craftd-core", version.ref = "craftdCompose" } +kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } +kotlin-testJunit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } +junit = { module = "junit:junit", version.ref = "junit" } +androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-core" } +androidx-testExt-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-testExt" } +androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-espresso" } +androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" } +androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" } +androidx-lifecycle-viewmodelCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" } +androidx-lifecycle-runtimeCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } +kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutinesCore" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } +kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlinx-collections-immutable" } + +[plugins] +androidApplication = { id = "com.android.application", version.ref = "agp" } +androidLibrary = { id = "com.android.library", version.ref = "agp" } +composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "composeMultiplatform" } +composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } \ No newline at end of file diff --git a/android_kmp/KMP-Sample/gradle/wrapper/gradle-wrapper.jar b/android_kmp/KMP-Sample/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..1b33c55 Binary files /dev/null and b/android_kmp/KMP-Sample/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android_kmp/KMP-Sample/gradle/wrapper/gradle-wrapper.properties b/android_kmp/KMP-Sample/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..e2847c8 --- /dev/null +++ b/android_kmp/KMP-Sample/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/android_kmp/KMP-Sample/gradlew b/android_kmp/KMP-Sample/gradlew new file mode 100755 index 0000000..23d15a9 --- /dev/null +++ b/android_kmp/KMP-Sample/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/android_kmp/KMP-Sample/gradlew.bat b/android_kmp/KMP-Sample/gradlew.bat new file mode 100644 index 0000000..db3a6ac --- /dev/null +++ b/android_kmp/KMP-Sample/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android_kmp/KMP-Sample/iosApp/Configuration/Config.xcconfig b/android_kmp/KMP-Sample/iosApp/Configuration/Config.xcconfig new file mode 100644 index 0000000..62ce44f --- /dev/null +++ b/android_kmp/KMP-Sample/iosApp/Configuration/Config.xcconfig @@ -0,0 +1,7 @@ +TEAM_ID= + +PRODUCT_NAME=KMP-Sample +PRODUCT_BUNDLE_IDENTIFIER=org.example.project.KMP-Sample$(TEAM_ID) + +CURRENT_PROJECT_VERSION=1 +MARKETING_VERSION=1.0 \ No newline at end of file diff --git a/android_kmp/KMP-Sample/iosApp/iosApp.xcodeproj/project.pbxproj b/android_kmp/KMP-Sample/iosApp/iosApp.xcodeproj/project.pbxproj new file mode 100644 index 0000000..63848ee --- /dev/null +++ b/android_kmp/KMP-Sample/iosApp/iosApp.xcodeproj/project.pbxproj @@ -0,0 +1,375 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXFileReference section */ + 1C6D5D6AEED764F150B58234 /* KMP-Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "KMP-Sample.app"; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + DD4F3A6E0BEF16C61F9E520E /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = 8A7966F07A76D1CD44D5D9A0 /* iosApp */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 186F065D2790AB03C5519CDB /* Configuration */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = Configuration; + sourceTree = ""; + }; + 460BCC607CED76E03E66BCB1 /* iosApp */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + DD4F3A6E0BEF16C61F9E520E /* PBXFileSystemSynchronizedBuildFileExceptionSet */, + ); + path = iosApp; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 98C663315D8315764846D464 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 47B33B1E94C517C9648A17F8 = { + isa = PBXGroup; + children = ( + 186F065D2790AB03C5519CDB /* Configuration */, + 460BCC607CED76E03E66BCB1 /* iosApp */, + 8EDB1AF49670CF89697EE5CC /* Products */, + ); + sourceTree = ""; + }; + 8EDB1AF49670CF89697EE5CC /* Products */ = { + isa = PBXGroup; + children = ( + 1C6D5D6AEED764F150B58234 /* KMP-Sample.app */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8A7966F07A76D1CD44D5D9A0 /* iosApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = B3DA73551DFE5C760F6BAE0C /* Build configuration list for PBXNativeTarget "iosApp" */; + buildPhases = ( + DBB26F6D35B891A8C039AA55 /* Compile Kotlin Framework */, + 94266FB9F877C4D28E1523B9 /* Sources */, + 98C663315D8315764846D464 /* Frameworks */, + 4EE63F0558EB3D826FF64E52 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 460BCC607CED76E03E66BCB1 /* iosApp */, + ); + name = iosApp; + packageProductDependencies = ( + ); + productName = iosApp; + productReference = 1C6D5D6AEED764F150B58234 /* KMP-Sample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D485713DA410197906CD867F /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1620; + LastUpgradeCheck = 1620; + TargetAttributes = { + 8A7966F07A76D1CD44D5D9A0 = { + CreatedOnToolsVersion = 16.2; + }; + }; + }; + buildConfigurationList = E7CA328A9B093AD22CA3FF50 /* Build configuration list for PBXProject "iosApp" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 47B33B1E94C517C9648A17F8; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = 8EDB1AF49670CF89697EE5CC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8A7966F07A76D1CD44D5D9A0 /* iosApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4EE63F0558EB3D826FF64E52 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + DBB26F6D35B891A8C039AA55 /* Compile Kotlin Framework */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Compile Kotlin Framework"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\ncd \"$SRCROOT/..\"\n./gradlew :composeApp:embedAndSignAppleFrameworkForXcode\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 94266FB9F877C4D28E1523B9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 36637EB77600F59FAC279BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = arm64; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; + DEVELOPMENT_TEAM = "${TEAM_ID}"; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = iosApp/Info.plist; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 17.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 4B2DA88F7255D3CC1C0053B8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = 186F065D2790AB03C5519CDB /* Configuration */; + baseConfigurationReferenceRelativePath = Config.xcconfig; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.2; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 57024DBAD30D247B7DC32964 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = arm64; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; + DEVELOPMENT_TEAM = "${TEAM_ID}"; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = iosApp/Info.plist; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 17.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + D22FFC51FE50EC82F2E5EC06 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = 186F065D2790AB03C5519CDB /* Configuration */; + baseConfigurationReferenceRelativePath = Config.xcconfig; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.2; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B3DA73551DFE5C760F6BAE0C /* Build configuration list for PBXNativeTarget "iosApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 36637EB77600F59FAC279BE5 /* Debug */, + 57024DBAD30D247B7DC32964 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E7CA328A9B093AD22CA3FF50 /* Build configuration list for PBXProject "iosApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D22FFC51FE50EC82F2E5EC06 /* Debug */, + 4B2DA88F7255D3CC1C0053B8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D485713DA410197906CD867F /* Project object */; +} diff --git a/android_kmp/KMP-Sample/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/android_kmp/KMP-Sample/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/android_kmp/KMP-Sample/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json b/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..4e8d485 --- /dev/null +++ b/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,36 @@ +{ + "images" : [ + { + "filename" : "app-icon-1024.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png b/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png new file mode 100644 index 0000000..53fc536 Binary files /dev/null and b/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png differ diff --git a/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/Contents.json b/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/android_kmp/KMP-Sample/iosApp/iosApp/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/android_kmp/KMP-Sample/iosApp/iosApp/ContentView.swift b/android_kmp/KMP-Sample/iosApp/iosApp/ContentView.swift new file mode 100644 index 0000000..c765ff2 --- /dev/null +++ b/android_kmp/KMP-Sample/iosApp/iosApp/ContentView.swift @@ -0,0 +1,21 @@ +import UIKit +import SwiftUI +import ComposeApp + +struct ComposeView: UIViewControllerRepresentable { + func makeUIViewController(context: Context) -> UIViewController { + MainViewControllerKt.MainViewController() + } + + func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} +} + +struct ContentView: View { + var body: some View { + ComposeView() + .ignoresSafeArea() + } +} + + + diff --git a/android_kmp/KMP-Sample/iosApp/iosApp/Info.plist b/android_kmp/KMP-Sample/iosApp/iosApp/Info.plist new file mode 100644 index 0000000..11845e1 --- /dev/null +++ b/android_kmp/KMP-Sample/iosApp/iosApp/Info.plist @@ -0,0 +1,8 @@ + + + + + CADisableMinimumFrameDurationOnPhone + + + diff --git a/android_kmp/KMP-Sample/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json b/android_kmp/KMP-Sample/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/android_kmp/KMP-Sample/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/android_kmp/KMP-Sample/iosApp/iosApp/iOSApp.swift b/android_kmp/KMP-Sample/iosApp/iosApp/iOSApp.swift new file mode 100644 index 0000000..d83dca6 --- /dev/null +++ b/android_kmp/KMP-Sample/iosApp/iosApp/iOSApp.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct iOSApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} \ No newline at end of file diff --git a/android_kmp/KMP-Sample/settings.gradle.kts b/android_kmp/KMP-Sample/settings.gradle.kts new file mode 100644 index 0000000..208df13 --- /dev/null +++ b/android_kmp/KMP-Sample/settings.gradle.kts @@ -0,0 +1,33 @@ +rootProject.name = "KMP-Sample" +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + +pluginManagement { + repositories { + google { + mavenContent { + includeGroupAndSubgroups("androidx") + includeGroupAndSubgroups("com.android") + includeGroupAndSubgroups("com.google") + } + } + mavenCentral() + gradlePluginPortal() + mavenLocal() + } +} + +dependencyResolutionManagement { + repositories { + google { + mavenContent { + includeGroupAndSubgroups("androidx") + includeGroupAndSubgroups("com.android") + includeGroupAndSubgroups("com.google") + } + } + mavenCentral() + mavenLocal() + } +} + +include(":composeApp") \ No newline at end of file diff --git a/android_kmp/README.md b/android_kmp/README.md index 5e73734..a66e114 100644 --- a/android_kmp/README.md +++ b/android_kmp/README.md @@ -1,276 +1,87 @@ -## Setup +# CraftD – Local KMP Testing Guide -Add in your settings.gradle `mavenCetral` -```kotlin -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - //Stuff - mavenCentral() - } - -} -``` - -### There are tree versions for Android: -- [Compose](#compose-version) +This guide explains how to build and publish the CraftD modules to your local Maven repository, then run the **KMP-Sample** app using those locally published artifacts. -```kotlin -implementation("io.github.codandotv:craftd-compose:${last_version}") -``` -Check out the latest version of the Compose library on [Maven Central Repository](https://central.sonatype.com/artifact/io.github.codandotv/craftd-compose) +## Prerequisites -- [XML View System](#xml-version) -```kotlin -implementation("io.github.codandotv:craftd-xml:${last_version}") -``` -Check out the latest version of the Xml library on [Maven Central Repository](https://central.sonatype.com/artifact/io.github.codandotv/craftd-xml) +* JDK 17+ +* Gradle Wrapper (`./gradlew`) +* macOS or Linux +* Kotlin Multiplatform toolchain installed (Xcode required for iOS builds) -- [Core](#core) - Is meant to be used for you to customize even the craftD mechanism -```kotlin -implementation("io.github.codandotv:craftd-core:${last_version}") -``` -Check out the latest version of the Core library on [Maven Central Repository](https://central.sonatype.com/artifact/io.github.codandotv/craftd-core) +--- -## How to use +## 1) Run the local publish script -### 🎯 Compose version +From the **android_kmp** repository root, run: -### 1. Create your ComponentPropertyClass with properties that you need -- In this example we used checkbox component -- To use json anotation we used jackson library, feel free to user your. +```bash +chmod +x generate_local_libraries.sh +./generate_local_libraries.sh +``` -> :bulb: **Tip:** Current version: **1.0.2** +What this script does automatically: -> :warning: **Warning:** Here we have some points to consider -> To avoid unnecessary recompositions at your component. We recommend use -> the @Immutable and @Stable annotations in your properties. More about it below +* Updates the `VERSION` / `VERSION_NAME` fields inside + `craftd-core/gradle.properties` and `craftd-compose/gradle.properties` +* Builds **release** artifacts of each module +* Publishes both modules to your `mavenLocal()` +* Updates `KMP-Sample/gradle/libs.versions.toml` + (key: `craftdCompose`) to the same version you just published -- **@immutable**: This guarantee the composition optimization based on the assumption that values read from the type will not change. +To force a specific version: -- **@stable**: this is used to communicate some guarantees to the compose compiler about how a certain type or function will behave and keep the compose compiler notified about changes +```bash +VERSION=1.0.5-local ./generate_local_libraries.sh +``` -```kotlin -@JsonIgnoreProperties(ignoreUnknown = true) -@Immutable -@Stable -data class CheckBoxProperties( - @JsonProperty("text") val text: String? = null, - ... define your properties here -) +Published artifacts will be located at: ``` - -### 2. Add your Component json object in Dymanic.json -```json -{ - "key": "CraftDCheckBox", - "value": { - ... define your properties here - } - } - +~/.m2/repository/io/github/codandotv/ ``` -### 3. Create your Component -> :memo: **Note:** Your composable component must have three properties. -- componentProperties: The mapped properties from json -- modifier: Default for composable componets -- behaviour: This make reference to the component's behaviour, for example: onclick -> for buttons, onchange -> for checkbox etc... -```kotlin -@Composable -fun CraftDCheckBox( - checkboxProperties: CheckBoxProperties, - modifier: Modifier = Modifier, - onChecked: (Boolean) -> Unit -) { - ... place your code -} -``` +--- -### 4. Create your Component Builder -> :memo: **Note:** This Builder must extend CraftBuilder Class and override craft method. +## 2) Ensure the sample uses `mavenLocal()` -```kotlin -class CraftDCheckBoxBuilder( - override val key: String = CraftDComponentKey.CHECK_BOX_COMPONENT.key -) : - CraftDBuilder { - @Composable - override fun craft(model: SimpleProperties, listener: CraftDViewListener) { - val checkBoxProperties = model.value.convertToVO() - CraftDCheckBox(checkBoxProperties) { - checkBoxProperties.actionProperties?.let { listener.invoke(it) } - } - } -} -``` +Inside **KMP-Sample**, confirm your `repositories` block contains: -### 5. In your screen you can add the builder inside of CraftBuilderManager ```kotlin -@Composable -fun InitialScreen( - vm: SampleCraftDComposeViewModel -) { - val properties by vm.properties.collectAsStateWithLifecycle() - val dynamicBuilder = remember { - CraftDBuilderManager().add( - CraftDCheckBoxBuilder() - ) - } - LaunchedEffect(Unit) { - vm.loadProperties() - } - - CraftDynamic( - properties = properties, - dynamicBuilder = dynamicBuilder - ) { - //Component click return to do something - } +repositories { + mavenLocal() + mavenCentral() } ``` -## So now just enjoy your component!!! - ------------------------------------------- -### 🎯 XML version +`mavenLocal()` must appear before `mavenCentral()`. -### 1. Add in a xml that you want to use -```xml - - +--- - +## 3) Build and run the sample app - +After running the script (which updates everything for you): -``` - -### 2. Add in your ViewModel the interface from the Dynamic +### Android -```kotlin -class YourViewModel( - val craft: CraftDView, - val repository: DynamicRepository -) : ViewModel() { - //Stuffs -} +```bash +./gradlew :composeApp:installDebug ``` -### 3. In your Activity/Fragment connect the Dynamic to the adapter in xml - -```kotlin - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = ActivityDynamicComponentBinding.inflate(layoutInflater) - setContentView(binding.root) +### iOS (XCFramework) - binding.recycler.adapter = vm.craft as CraftDViewAdapter - //--- Stuffs -} +```bash +./gradlew :composeApp:assembleComposeAppDebugXCFramework ``` +Or simply open the sample project: -### 4. Create object `Properties` of according with your components for example: ``` -@JsonIgnoreProperties(ignoreUnknown = true) -data class TextProperties( - @JsonProperty("xxx") val myProperties1: String, - @JsonProperty("xxx") val myProperties2: String, -) +File > Open > android_kmp/KMP-Sample ``` -### 5. Create object `ViewRenders` of according with your components for example: - -```kotlin -class MyComponentRender(override var onClickListener: CraftDViewListener?) - : ViewRenderer("Your Key", "Your Identifier") { - - inner class MyHolder(val anyView: AnyView) : RecyclerView.ViewHolder(anyView) - - override fun bindView(model: SimpleProperties, holder: MyHolder, position: Int) { - val anyProperties = model.value.convertToVO() +--- - holder.any.text = anyProperties.text - anyProperties.textColorHex?.let { textColorHex -> - //Stuff - } - anyProperties.actionProperties?.let { actionProperties -> - //Stuff - } - } +## ✅ Finished! - override fun createViewHolder(parent: ViewGroup): MyHolder { - return MyHolder(AnyView(parent.context)) - } -} -``` - -### 6. Configure your ViewModel to accept for example: - -```kotlin -class DynamicViewModel( - val craft: CraftD, - val repository: SampleCraftDRepository -) : ViewModel() { - - fun onResume() { - viewModelScope.launch { - repository.getDynamic() - .catch { - it.printStackTrace() - } - .collect { - setupDynamicRender(it) - craft.setViewObjectDiff(it) - } - } - } - - private fun setupDynamicRender(list: List) { - craft.registerRenderers( - CraftDBuilderManager.getBuilderRenders( - simpleProperties = list, - customDynamicBuilderList = customListViewRender // Can you pass your custom list from ViewRender - ) { action -> - listener.invoke(action) - }) - } - - private val listener = object : CraftDViewListener { - override fun invoke(actionProperties: ActionProperties) { - actionProperties.analytics?.let { - //Stuff - } - actionProperties.deeplink?.let { - //Stuff - } - } - } -} -``` - -## 7. Enjoy and Have fun to create a json that you need - -Your json must to have at least two parameters `key` and `value` that are respective of your object for example: -```json -{ - "data": [ - { - "key": "MyDynamicView", - "value": { - "text": "Any", - "textColor": "Any" - } - } - ] -} -``` +Your environment is now ready for local testing of CraftD KMP modules using the exact version generated by the script. diff --git a/android_kmp/app-sample/.gitignore b/android_kmp/app-sample-android/.gitignore similarity index 100% rename from android_kmp/app-sample/.gitignore rename to android_kmp/app-sample-android/.gitignore diff --git a/android_kmp/app-sample/build.gradle.kts b/android_kmp/app-sample-android/build.gradle.kts similarity index 57% rename from android_kmp/app-sample/build.gradle.kts rename to android_kmp/app-sample-android/build.gradle.kts index 2f62200..db9d4b4 100644 --- a/android_kmp/app-sample/build.gradle.kts +++ b/android_kmp/app-sample-android/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("com.codandotv.application") alias(libs.plugins.jetbrains.compose) + alias(libs.plugins.kotlin.compose) } android { @@ -11,69 +12,52 @@ android { dependencies { val koin_version = "2.2.3" + val lifecycle_version = "2.7.0" + implementation(libs.kotlinx.serialization.json) + implementation(projects.craftdCore) - implementation(projects.craftdXml) +// implementation(projects.craftdXml) implementation(projects.craftdCompose) - implementation("androidx.core:core-ktx:1.13.0") - implementation("androidx.appcompat:appcompat:1.6.1") - implementation("io.github.codandotv:craftd-xml:0.0.1") - implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.7.0") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0") + implementation(libs.androidx.core) + implementation(libs.androidx.appcompat) + implementation(libs.google.material) + implementation(libs.kotlinx.collections.immutable) + + implementation("io.github.codandotv:craftd-xml:1.1.0") // revisar se Ă© necessĂĄrio junto com `projects.craftdXml` + + implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version") + implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version") + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version") implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-simplexml:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") - implementation("com.squareup.retrofit2:converter-moshi:2.9.0") - implementation("com.squareup.okhttp3:logging-interceptor:4.9.1") implementation("com.squareup.okhttp3:okhttp:4.9.1") - implementation("com.fasterxml.jackson.core:jackson-core:2.12.4") - implementation("com.fasterxml.jackson.core:jackson-databind:2.12.4") + implementation("com.squareup.okhttp3:logging-interceptor:4.9.1") implementation("com.squareup.picasso:picasso:2.8") - // Koin AndroidX Scope features implementation("io.insert-koin:koin-androidx-scope:$koin_version") - // Koin AndroidX ViewModel features implementation("io.insert-koin:koin-androidx-viewmodel:$koin_version") - // Koin AndroidX Fragment features implementation("io.insert-koin:koin-androidx-fragment:$koin_version") - // Koin AndroidX Experimental features implementation("io.insert-koin:koin-androidx-ext:$koin_version") - implementation("com.google.android.material:material:1.11.0") implementation("androidx.constraintlayout:constraintlayout:2.1.4") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1"); - - val lifecycle_version = "2.7.0" - // Lifecycle utilities for Compose - implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version") val composeBom = platform("androidx.compose:compose-bom:2024.02.02") implementation(composeBom) androidTestImplementation(composeBom) - // Choose one of the following: - // Material Design 3 implementation("androidx.compose.material3:material3") - // or only import the main APIs for the underlying toolkit systems, - // such as input and measurement/layout implementation("androidx.compose.ui:ui") - - // Android Studio Preview support implementation("androidx.compose.ui:ui-tooling-preview") - debugImplementation("androidx.compose.ui:ui-tooling") - - - // Optional - Included automatically by material, only add when you need - // the icons but not the material library (e.g. when using Material3 or a - // custom design system based on Foundation) + implementation("androidx.activity:activity-compose:1.8.2") implementation("androidx.compose.material:material-icons-core") - // Optional - Integration with activities - implementation("androidx.activity:activity-compose:1.8.2") - // Optional - Integration with ViewModels - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0") - implementation(libs.kotlinx.collections.immutable) -} \ No newline at end of file + debugImplementation("androidx.compose.ui:ui-tooling") + + testImplementation(libs.junit) + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") +} diff --git a/android_kmp/app-sample/proguard-rules.pro b/android_kmp/app-sample-android/proguard-rules.pro similarity index 100% rename from android_kmp/app-sample/proguard-rules.pro rename to android_kmp/app-sample-android/proguard-rules.pro diff --git a/android_kmp/app-sample/src/androidTest/java/com/github/codandotv/craftd/app_sample/ExampleInstrumentedTest.kt b/android_kmp/app-sample-android/src/androidTest/java/com/github/codandotv/craftd/app_sample/ExampleInstrumentedTest.kt similarity index 100% rename from android_kmp/app-sample/src/androidTest/java/com/github/codandotv/craftd/app_sample/ExampleInstrumentedTest.kt rename to android_kmp/app-sample-android/src/androidTest/java/com/github/codandotv/craftd/app_sample/ExampleInstrumentedTest.kt diff --git a/android_kmp/app-sample/src/main/AndroidManifest.xml b/android_kmp/app-sample-android/src/main/AndroidManifest.xml similarity index 92% rename from android_kmp/app-sample/src/main/AndroidManifest.xml rename to android_kmp/app-sample-android/src/main/AndroidManifest.xml index 3b9b6e4..52a191a 100644 --- a/android_kmp/app-sample/src/main/AndroidManifest.xml +++ b/android_kmp/app-sample-android/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ - + + + + + + - - - - diff --git a/android_kmp/app-sample/src/main/assets/dynamic.json b/android_kmp/app-sample-android/src/main/assets/dynamic.json similarity index 100% rename from android_kmp/app-sample/src/main/assets/dynamic.json rename to android_kmp/app-sample-android/src/main/assets/dynamic.json diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/CustomApplication.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/CustomApplication.kt similarity index 100% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/CustomApplication.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/CustomApplication.kt diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/data/SampleCraftDRepository.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/data/SampleCraftDRepository.kt similarity index 66% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/data/SampleCraftDRepository.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/data/SampleCraftDRepository.kt index ae05975..2ba2b34 100644 --- a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/data/SampleCraftDRepository.kt +++ b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/data/SampleCraftDRepository.kt @@ -8,6 +8,8 @@ import com.github.codandotv.craftd.androidcore.extensions.loadJSONFromAsset import com.google.gson.Gson import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.json.Json interface SampleCraftDRepository { suspend fun getDynamic(): Flow> @@ -19,12 +21,11 @@ class SampleCraftDRepositoryImpl( private val service: SampleCraftDSampleService ) : SampleCraftDRepository { override suspend fun getDynamic(): Flow> = flow { - emit(service.getDynamicExample().toListSimpleProperties()) -// emit( -// gson.fromJson( -// context.loadJSONFromAsset("dynamic"), -// Array::class.java -// ).asList().toListSimpleProperties() -// ) +// emit(service.getDynamicExample().toListSimpleProperties()) + val jsonString = context.loadJSONFromAsset("dynamic") + val list = Json { ignoreUnknownKeys = true } + .decodeFromString(ListSerializer(SimplePropertiesResponse.serializer()), jsonString) + .toListSimpleProperties() + emit(list) } } diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/data/SampleCraftDSampleService.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/data/SampleCraftDSampleService.kt similarity index 100% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/data/SampleCraftDSampleService.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/data/SampleCraftDSampleService.kt diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/di/AppModule.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/di/AppModule.kt similarity index 100% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/di/AppModule.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/di/AppModule.kt diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/domain/OkhttpExtensions.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/domain/OkhttpExtensions.kt similarity index 100% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/domain/OkhttpExtensions.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/domain/OkhttpExtensions.kt diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/InitialScreen.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/InitialScreen.kt similarity index 100% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/InitialScreen.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/InitialScreen.kt diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/SampleCraftDComposeActivity.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/SampleCraftDComposeActivity.kt similarity index 100% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/SampleCraftDComposeActivity.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/SampleCraftDComposeActivity.kt diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/SampleCraftDComposeViewModel.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/SampleCraftDComposeViewModel.kt similarity index 100% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/SampleCraftDComposeViewModel.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/SampleCraftDComposeViewModel.kt diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/customview/MySampleButton.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/customview/MySampleButton.kt similarity index 100% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/customview/MySampleButton.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/customview/MySampleButton.kt diff --git a/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/customview/MySampleButtonComposeBuilder.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/customview/MySampleButtonComposeBuilder.kt new file mode 100644 index 0000000..3c2d0ac --- /dev/null +++ b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/compose/customview/MySampleButtonComposeBuilder.kt @@ -0,0 +1,19 @@ +package com.github.codandotv.craftd.app_sample.presentation.compose.customview + +import androidx.compose.runtime.Composable +import com.github.codandotv.craftd.androidcore.data.convertToElement +import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties +import com.github.codandotv.craftd.androidcore.data.model.button.ButtonProperties +import com.github.codandotv.craftd.compose.builder.CraftDBuilder + +class MySampleButtonComposeBuilder(override val key: String = "MySampleButton") : CraftDBuilder { + @Composable + override fun craft(model: SimpleProperties, listener: com.github.codandotv.craftd.androidcore.presentation.CraftDViewListener) { + val buttonProperties = model.value.convertToElement() + buttonProperties?.let { + MySampleButton(it) { + buttonProperties.actionProperties?.let { listener.invoke(it) } + } + } + } +} \ No newline at end of file diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml/SampleCraftDComponentActivity.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml/SampleCraftDComponentActivity.kt similarity index 100% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml/SampleCraftDComponentActivity.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml/SampleCraftDComponentActivity.kt diff --git a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml/SampleCraftDViewModel.kt b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml/SampleCraftDViewModel.kt similarity index 88% rename from android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml/SampleCraftDViewModel.kt rename to android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml/SampleCraftDViewModel.kt index d28af51..170c7d9 100644 --- a/android_kmp/app-sample/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml/SampleCraftDViewModel.kt +++ b/android_kmp/app-sample-android/src/main/java/com/github/codandotv/craftd/app_sample/presentation/xml/SampleCraftDViewModel.kt @@ -44,8 +44,9 @@ class SampleCraftDViewModel( }) } - private val listener = object : CraftDViewListener { - override fun invoke(actionProperties: ActionProperties) { + private val listener = object : + com.github.codandotv.craftd.androidcore.presentation.CraftDViewListener { + override fun invoke(actionProperties: com.github.codandotv.craftd.androidcore.data.model.action.ActionProperties) { actionProperties.analytics?.let { _analytics.value = "categoria: ${it.category}, ação: ${it.action}, label: ${it.label}" diff --git a/android_kmp/app-sample-android/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android_kmp/app-sample-android/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/android_kmp/app-sample-android/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample/src/main/res/drawable/ic_launcher_background.xml b/android_kmp/app-sample-android/src/main/res/drawable/ic_launcher_background.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/drawable/ic_launcher_background.xml rename to android_kmp/app-sample-android/src/main/res/drawable/ic_launcher_background.xml diff --git a/android_kmp/app-sample/src/main/res/layout/activity_dynamic_component.xml b/android_kmp/app-sample-android/src/main/res/layout/activity_dynamic_component.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/layout/activity_dynamic_component.xml rename to android_kmp/app-sample-android/src/main/res/layout/activity_dynamic_component.xml diff --git a/android_kmp/app-sample/src/main/res/layout/activity_main.xml b/android_kmp/app-sample-android/src/main/res/layout/activity_main.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/layout/activity_main.xml rename to android_kmp/app-sample-android/src/main/res/layout/activity_main.xml diff --git a/android_kmp/app-sample-android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android_kmp/app-sample-android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/android_kmp/app-sample-android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample-android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android_kmp/app-sample-android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/android_kmp/app-sample-android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample/src/main/res/mipmap-hdpi/ic_launcher.webp b/android_kmp/app-sample-android/src/main/res/mipmap-hdpi/ic_launcher.webp similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-hdpi/ic_launcher.webp rename to android_kmp/app-sample-android/src/main/res/mipmap-hdpi/ic_launcher.webp diff --git a/android_kmp/app-sample/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/android_kmp/app-sample-android/src/main/res/mipmap-hdpi/ic_launcher_round.webp similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-hdpi/ic_launcher_round.webp rename to android_kmp/app-sample-android/src/main/res/mipmap-hdpi/ic_launcher_round.webp diff --git a/android_kmp/app-sample/src/main/res/mipmap-mdpi/ic_launcher.webp b/android_kmp/app-sample-android/src/main/res/mipmap-mdpi/ic_launcher.webp similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-mdpi/ic_launcher.webp rename to android_kmp/app-sample-android/src/main/res/mipmap-mdpi/ic_launcher.webp diff --git a/android_kmp/app-sample/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/android_kmp/app-sample-android/src/main/res/mipmap-mdpi/ic_launcher_round.webp similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-mdpi/ic_launcher_round.webp rename to android_kmp/app-sample-android/src/main/res/mipmap-mdpi/ic_launcher_round.webp diff --git a/android_kmp/app-sample/src/main/res/mipmap-xhdpi/ic_launcher.webp b/android_kmp/app-sample-android/src/main/res/mipmap-xhdpi/ic_launcher.webp similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-xhdpi/ic_launcher.webp rename to android_kmp/app-sample-android/src/main/res/mipmap-xhdpi/ic_launcher.webp diff --git a/android_kmp/app-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/android_kmp/app-sample-android/src/main/res/mipmap-xhdpi/ic_launcher_round.webp similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.webp rename to android_kmp/app-sample-android/src/main/res/mipmap-xhdpi/ic_launcher_round.webp diff --git a/android_kmp/app-sample/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/android_kmp/app-sample-android/src/main/res/mipmap-xxhdpi/ic_launcher.webp similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-xxhdpi/ic_launcher.webp rename to android_kmp/app-sample-android/src/main/res/mipmap-xxhdpi/ic_launcher.webp diff --git a/android_kmp/app-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/android_kmp/app-sample-android/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp rename to android_kmp/app-sample-android/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp diff --git a/android_kmp/app-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/android_kmp/app-sample-android/src/main/res/mipmap-xxxhdpi/ic_launcher.webp similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp rename to android_kmp/app-sample-android/src/main/res/mipmap-xxxhdpi/ic_launcher.webp diff --git a/android_kmp/app-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/android_kmp/app-sample-android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp similarity index 100% rename from android_kmp/app-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp rename to android_kmp/app-sample-android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp diff --git a/android_kmp/app-sample/src/main/res/values-night/themes.xml b/android_kmp/app-sample-android/src/main/res/values-night/themes.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/values-night/themes.xml rename to android_kmp/app-sample-android/src/main/res/values-night/themes.xml diff --git a/android_kmp/app-sample/src/main/res/values/colors.xml b/android_kmp/app-sample-android/src/main/res/values/colors.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/values/colors.xml rename to android_kmp/app-sample-android/src/main/res/values/colors.xml diff --git a/android_kmp/app-sample/src/main/res/values/strings.xml b/android_kmp/app-sample-android/src/main/res/values/strings.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/values/strings.xml rename to android_kmp/app-sample-android/src/main/res/values/strings.xml diff --git a/android_kmp/app-sample/src/main/res/values/themes.xml b/android_kmp/app-sample-android/src/main/res/values/themes.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/values/themes.xml rename to android_kmp/app-sample-android/src/main/res/values/themes.xml diff --git a/android_kmp/app-sample/src/main/res/xml/network_security_config.xml b/android_kmp/app-sample-android/src/main/res/xml/network_security_config.xml similarity index 100% rename from android_kmp/app-sample/src/main/res/xml/network_security_config.xml rename to android_kmp/app-sample-android/src/main/res/xml/network_security_config.xml diff --git a/android_kmp/app-sample/src/test/java/com/github/codandotv/craftd/app_sample/ExampleUnitTest.kt b/android_kmp/app-sample-android/src/test/java/com/github/codandotv/craftd/app_sample/ExampleUnitTest.kt similarity index 100% rename from android_kmp/app-sample/src/test/java/com/github/codandotv/craftd/app_sample/ExampleUnitTest.kt rename to android_kmp/app-sample-android/src/test/java/com/github/codandotv/craftd/app_sample/ExampleUnitTest.kt diff --git a/android_kmp/app-sample-cmp/build.gradle.kts b/android_kmp/app-sample-cmp/build.gradle.kts new file mode 100644 index 0000000..e5a5f83 --- /dev/null +++ b/android_kmp/app-sample-cmp/build.gradle.kts @@ -0,0 +1,63 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.jetbrains.compose) + alias(libs.plugins.kotlin.compose) + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.serialization) +} + +android { + namespace = "com.codandotv.appsamplecmp" + + defaultConfig { + applicationId = "org.example.project" + minSdk = 24 + targetSdk = 36 + compileSdk = 36 + versionCode = 1 + versionName = "1.0" + } +} + +kotlin { + androidTarget { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + freeCompilerArgs.add("-Xstring-concat=inline") + } + } + + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "ComposeApp" + isStatic = false + } + } + + sourceSets { + androidMain.dependencies { + implementation(compose.preview) + implementation(libs.androidx.activity.compose) + } + commonMain.dependencies { + implementation(projects.craftdCompose) + implementation(compose.runtime) + implementation(libs.kotlinx.coroutines.core) + implementation(libs.kotlinx.serialization.json) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.ui) + implementation(compose.components.uiToolingPreview) + implementation(libs.androidx.lifecycle.viewmodelCompose) + implementation(libs.androidx.lifecycle.runtimeCompose) + implementation(libs.kotlinx.collections.immutable) + implementation(compose.components.resources) + } + } +} \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/androidMain/AndroidManifest.xml b/android_kmp/app-sample-cmp/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000..871b845 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/androidMain/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/androidMain/kotlin/org/example/project/MainActivity.kt b/android_kmp/app-sample-cmp/src/androidMain/kotlin/org/example/project/MainActivity.kt new file mode 100644 index 0000000..e2bb0ed --- /dev/null +++ b/android_kmp/app-sample-cmp/src/androidMain/kotlin/org/example/project/MainActivity.kt @@ -0,0 +1,25 @@ +package org.example.project + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() + super.onCreate(savedInstanceState) + + setContent { + App() + } + } +} + +@Preview +@Composable +fun AppAndroidPreview() { + App() +} \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/androidMain/kotlin/org/example/project/Platform.android.kt b/android_kmp/app-sample-cmp/src/androidMain/kotlin/org/example/project/Platform.android.kt new file mode 100644 index 0000000..63d6f9f --- /dev/null +++ b/android_kmp/app-sample-cmp/src/androidMain/kotlin/org/example/project/Platform.android.kt @@ -0,0 +1,9 @@ +package org.example.project + +import android.os.Build + +class AndroidPlatform : Platform { + override val name: String = "Android ${Build.VERSION.SDK_INT}" +} + +actual fun getPlatform(): Platform = AndroidPlatform() \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml b/android_kmp/app-sample-cmp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/drawable/ic_launcher_background.xml b/android_kmp/app-sample-cmp/src/androidMain/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..e93e11a --- /dev/null +++ b/android_kmp/app-sample-cmp/src/androidMain/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-hdpi/ic_launcher.png b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a571e60 Binary files /dev/null and b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..61da551 Binary files /dev/null and b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-mdpi/ic_launcher.png b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..c41dd28 Binary files /dev/null and b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..db5080a Binary files /dev/null and b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6dba46d Binary files /dev/null and b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..da31a87 Binary files /dev/null and b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..15ac681 Binary files /dev/null and b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..b216f2d Binary files /dev/null and b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..f25a419 Binary files /dev/null and b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..e96783c Binary files /dev/null and b/android_kmp/app-sample-cmp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/android_kmp/app-sample-cmp/src/androidMain/res/values/strings.xml b/android_kmp/app-sample-cmp/src/androidMain/res/values/strings.xml new file mode 100644 index 0000000..84cb5ca --- /dev/null +++ b/android_kmp/app-sample-cmp/src/androidMain/res/values/strings.xml @@ -0,0 +1,3 @@ + + KMP-Sample + \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/commonMain/composeResources/drawable/compose-multiplatform.xml b/android_kmp/app-sample-cmp/src/commonMain/composeResources/drawable/compose-multiplatform.xml new file mode 100644 index 0000000..1ffc948 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/commonMain/composeResources/drawable/compose-multiplatform.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/commonMain/composeResources/files/dynamic.json b/android_kmp/app-sample-cmp/src/commonMain/composeResources/files/dynamic.json new file mode 100644 index 0000000..5997a18 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/commonMain/composeResources/files/dynamic.json @@ -0,0 +1,371 @@ +[ + { + "key": "CraftDTextView", + "value": { + "text": "KMP Works", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "textSize": "20", + "textColorHex": "#FF0000", + "align": "CENTER", + "textStyle": "BOLD", + "textAllCaps": true, + "textHtml": "

Este Ă© um texto em HTML

Isso Ă© itĂĄlico

" + } + }, + { + "key": "CraftDButton", + "value": { + "text": "Some Action :)", + "align": "CENTER", + "textAlign": "CENTER", + "textAllCaps": true, + "textSize": "20", + "textColorHex": "#FFFFFF", + "backgroundHex": "#2fa003", + "actionProperties": { + "deeplink": "CraftDview://any", + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + }, + { + "key": "CraftDCheckBox", + "value": { + "text": "Mark here ", + "align": "RIGHT", + "textAlign": "CENTER", + "hasItRightText": false, + "enable": true, + "style": { + "checkedColorHex": "#FF0000", + "uncheckedColorHex": " #808080" + }, + "actionProperties": { + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + }, + { + "key": "MySampleButton", + "value": { + "text": "MySampleButton", + "align": "RIGHT", + "textAlign": "CENTER", + "textAllCaps": true, + "textSize": "20", + "textColorHex": "#FFFFFF", + "backgroundHex": "#2fa003", + "actionProperties": { + "deeplink": "CraftDview://any", + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Knife", + "backgroundHex": "#9A71F6", + "textSize": "30", + "textColorHex": "#000000" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "textSize": "20", + "textColorHex": "#FF0000", + "align": "CENTER", + "textStyle": "BOLD", + "textAllCaps": true, + "textHtml": "

Este Ă© um texto em HTML

Isso Ă© itĂĄlico

" + } + }, + { + "key": "CraftDButton", + "value": { + "text": "Some Action :)", + "align": "RIGHT", + "textAlign": "CENTER", + "textAllCaps": true, + "textSize": "20", + "textColorHex": "#FFFFFF", + "backgroundHex": "#2fa003", + "actionProperties": { + "deeplink": "CraftDview://any", + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Knife", + "backgroundHex": "#9A71F6", + "textSize": "30", + "textColorHex": "#000000" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "textSize": "20", + "textColorHex": "#FF0000", + "align": "CENTER", + "textStyle": "BOLD", + "textAllCaps": true, + "textHtml": "

Este Ă© um texto em HTML

Isso Ă© itĂĄlico

" + } + }, + { + "key": "CraftDButton", + "value": { + "text": "Some Action :)", + "align": "RIGHT", + "textAlign": "CENTER", + "fillMaxSize": false, + "textAllCaps": true, + "textSize": "20", + "textColorHex": "#FFFFFF", + "backgroundHex": "#2fa003", + "actionProperties": { + "deeplink": "CraftDview://any", + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Knife", + "backgroundHex": "#9A71F6", + "textSize": "30", + "textColorHex": "#000000" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "text": "Axe", + "textSize": "40", + "textColorHex": "#D977EB" + } + }, + { + "key": "CraftDTextView", + "value": { + "textSize": "20", + "textColorHex": "#FF0000", + "align": "CENTER", + "textStyle": "BOLD", + "textAllCaps": true, + "textHtml": "

Este Ă© um texto em HTML

Isso Ă© itĂĄlico

" + } + }, + { + "key": "CraftDButton", + "value": { + "text": "Some Action :)", + "align": "RIGHT", + "textAlign": "CENTER", + "textAllCaps": true, + "textSize": "20", + "textColorHex": "#FFFFFF", + "backgroundHex": "#2fa003", + "actionProperties": { + "deeplink": "deeplink://any", + "analytics": { + "category": "hello", + "action": "world", + "label": "everywhere" + } + } + } + } +] \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/App.kt b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/App.kt new file mode 100644 index 0000000..4ba13a0 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/App.kt @@ -0,0 +1,14 @@ +package org.example.project + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import org.example.project.presentation.compose.InitialScreen +import org.jetbrains.compose.ui.tooling.preview.Preview + +@Composable +@Preview +fun App() { + MaterialTheme { + InitialScreen() + } +} \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/Greeting.kt b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/Greeting.kt new file mode 100644 index 0000000..d49d319 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/Greeting.kt @@ -0,0 +1,9 @@ +package org.example.project + +class Greeting { + private val platform = getPlatform() + + fun greet(): String { + return "Hello, ${platform.name}!" + } +} \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/Platform.kt b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/Platform.kt new file mode 100644 index 0000000..6018b28 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/Platform.kt @@ -0,0 +1,7 @@ +package org.example.project + +interface Platform { + val name: String +} + +expect fun getPlatform(): Platform \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/data/SampleCraftDRepository.kt b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/data/SampleCraftDRepository.kt new file mode 100644 index 0000000..8c6c832 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/data/SampleCraftDRepository.kt @@ -0,0 +1,24 @@ +package org.example.project.data + +import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties +import craftd.app_sample_cmp.generated.resources.Res +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.serialization.json.Json + +interface SampleCraftDRepository { + suspend fun getDynamic(): Flow> +} + +class SampleCraftDRepositoryImpl() : SampleCraftDRepository { + + override suspend fun getDynamic(): Flow> = flow { + val jsonString = Res.readBytes("files/dynamic.json") + .decodeToString() + + val list = Json { ignoreUnknownKeys = true } + .decodeFromString>(jsonString) + + emit(list) + } +} diff --git a/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/InitialScreen.kt b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/InitialScreen.kt new file mode 100644 index 0000000..f38c498 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/InitialScreen.kt @@ -0,0 +1,36 @@ +package org.example.project.presentation.compose + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import org.example.project.presentation.compose.customview.MySampleButtonComposeBuilder +import com.github.codandotv.craftd.compose.builder.CraftDBuilderManager +import com.github.codandotv.craftd.compose.ui.CraftDynamic +import org.example.project.data.SampleCraftDRepositoryImpl + +@Composable +fun InitialScreen( + vm: SampleCraftDComposeViewModel = SampleCraftDComposeViewModel(SampleCraftDRepositoryImpl()) +) { + val properties by vm.properties.collectAsState() + val craftdBuilderManager = remember { + CraftDBuilderManager().add( + MySampleButtonComposeBuilder(), + ) + } + LaunchedEffect(Unit) { + vm.loadProperties() + } + + CraftDynamic( + properties = properties, + craftDBuilderManager = craftdBuilderManager + ) { + println( + ">>>> category ${it.analytics?.category} -" + " action ${it.analytics?.action} -" + " label ${it.analytics?.label} -" + " deeplink ${it.deeplink}" + ) + } +} \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/SampleCraftDComposeViewModel.kt b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/SampleCraftDComposeViewModel.kt new file mode 100644 index 0000000..e71c7fd --- /dev/null +++ b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/SampleCraftDComposeViewModel.kt @@ -0,0 +1,33 @@ +package org.example.project.presentation.compose + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import org.example.project.data.SampleCraftDRepository + +class SampleCraftDComposeViewModel(private val repository: SampleCraftDRepository) : ViewModel() { + private val _properties = MutableStateFlow>(persistentListOf()) + val properties = _properties.stateIn( + viewModelScope, SharingStarted.Eagerly, + initialValue = _properties.value + ) + + fun loadProperties() { + viewModelScope.launch { + repository.getDynamic().collectLatest { newList -> + _properties.update { + newList.toImmutableList() + } + } + } + } +} \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButton.kt b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButton.kt new file mode 100644 index 0000000..6cde5a7 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButton.kt @@ -0,0 +1,32 @@ +package org.example.project.presentation.compose.customview + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.github.codandotv.craftd.androidcore.data.model.button.ButtonProperties +import com.github.codandotv.craftd.compose.extensions.toArrangementCompose + +@Composable +fun MySampleButton( + buttonProperties: ButtonProperties, + modifier: Modifier = Modifier, + onClick: () -> Unit, +) { + Row( + horizontalArrangement = buttonProperties.align.toArrangementCompose(), + modifier = Modifier.fillMaxWidth() + ) { + Button( + onClick = onClick, + colors = ButtonDefaults.buttonColors(containerColor = Color.Magenta), + modifier = modifier, + ) { + Text(buttonProperties.text ?: "empty") + } + } +} \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButtonComposeBuilder.kt b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButtonComposeBuilder.kt new file mode 100644 index 0000000..be47b57 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/commonMain/kotlin/org/example/project/presentation/compose/customview/MySampleButtonComposeBuilder.kt @@ -0,0 +1,20 @@ +package org.example.project.presentation.compose.customview + +import androidx.compose.runtime.Composable +import com.github.codandotv.craftd.androidcore.data.convertToElement +import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties +import com.github.codandotv.craftd.androidcore.data.model.button.ButtonProperties +import com.github.codandotv.craftd.androidcore.presentation.CraftDViewListener +import com.github.codandotv.craftd.compose.builder.CraftDBuilder + +class MySampleButtonComposeBuilder(override val key: String = "MySampleButton") : CraftDBuilder { + @Composable + override fun craft(model: SimpleProperties, listener: CraftDViewListener) { + val buttonProperties = model.value.convertToElement() + buttonProperties?.let { + MySampleButton(it) { + buttonProperties.actionProperties?.let { listener.invoke(it) } + } + } + } +} \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/iosMain/kotlin/org/example/project/MainViewController.kt b/android_kmp/app-sample-cmp/src/iosMain/kotlin/org/example/project/MainViewController.kt new file mode 100644 index 0000000..f235c15 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/iosMain/kotlin/org/example/project/MainViewController.kt @@ -0,0 +1,5 @@ +package org.example.project + +import androidx.compose.ui.window.ComposeUIViewController + +fun MainViewController() = ComposeUIViewController { App() } \ No newline at end of file diff --git a/android_kmp/app-sample-cmp/src/iosMain/kotlin/org/example/project/Platform.ios.kt b/android_kmp/app-sample-cmp/src/iosMain/kotlin/org/example/project/Platform.ios.kt new file mode 100644 index 0000000..aea8f33 --- /dev/null +++ b/android_kmp/app-sample-cmp/src/iosMain/kotlin/org/example/project/Platform.ios.kt @@ -0,0 +1,9 @@ +package org.example.project + +import platform.UIKit.UIDevice + +class IOSPlatform: Platform { + override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion +} + +actual fun getPlatform(): Platform = IOSPlatform() \ No newline at end of file diff --git a/android_kmp/build-logic/build.gradle.kts b/android_kmp/build-logic/build.gradle.kts index e14cf66..33c3b94 100644 --- a/android_kmp/build-logic/build.gradle.kts +++ b/android_kmp/build-logic/build.gradle.kts @@ -15,4 +15,5 @@ dependencies { implementation(libs.android.gradle.plugin) implementation(libs.kotlin.gradle.plugin) implementation(libs.plugin.maven) + implementation(libs.serialization) } \ No newline at end of file diff --git a/android_kmp/build-logic/settings.gradle.kts b/android_kmp/build-logic/settings.gradle.kts index c3b0279..dced325 100644 --- a/android_kmp/build-logic/settings.gradle.kts +++ b/android_kmp/build-logic/settings.gradle.kts @@ -1,5 +1,15 @@ +@file:Suppress("UnstableApiUsage") + +pluginManagement { + repositories { + gradlePluginPortal(); + google(); + mavenCentral() + } +} dependencyResolutionManagement { repositories { + google(); mavenCentral() } versionCatalogs { @@ -8,3 +18,4 @@ dependencyResolutionManagement { } } } +rootProject.name = "build-logic" diff --git a/android_kmp/build-logic/src/main/java/Config.kt b/android_kmp/build-logic/src/main/java/Config.kt index 95e8b8f..0c48793 100644 --- a/android_kmp/build-logic/src/main/java/Config.kt +++ b/android_kmp/build-logic/src/main/java/Config.kt @@ -1,10 +1,16 @@ +import org.gradle.api.JavaVersion +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + object Config { const val applicationId = "com.github.codandotv" - const val compileSdkVersion = 34 + const val compileSdkVersion = 35 const val minSdkVersion = 21 - const val targetSdkVersion = 34 + const val targetSdkVersion = 35 const val versionName = "1.0" const val versionCode = 1 - const val jvmTarget = "17" + val jvmTargetVersion = JavaVersion.VERSION_17 + val jvmTargetValue = JvmTarget.JVM_17 + val jvmTargetTool = Regex("\\d+").find(jvmTargetValue.toString())!!.value.toInt() const val testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + const val appName = "Craftd" } \ No newline at end of file diff --git a/android_kmp/build-logic/src/main/java/com.codandotv.android-library.gradle.kts b/android_kmp/build-logic/src/main/java/com.codandotv.android-library.gradle.kts index 2bde0e4..5a883e3 100644 --- a/android_kmp/build-logic/src/main/java/com.codandotv.android-library.gradle.kts +++ b/android_kmp/build-logic/src/main/java/com.codandotv.android-library.gradle.kts @@ -1,19 +1,15 @@ @file:Suppress("UnstableApiUsage") -import extensions.configurePlatformTargets import extensions.setupAndroidDefaultConfig import extensions.setupCompileOptions import extensions.setupNameSpace import extensions.setupPackingOptions -import org.gradle.api.artifacts.VersionCatalog -import org.gradle.api.artifacts.VersionCatalogsExtension - -val libs: VersionCatalog = extensions.getByType().named("libs") plugins { id("com.android.library") + id("kotlin-android") + id("kotlin-kapt") id("kotlin-parcelize") - id("org.jetbrains.kotlin.multiplatform") } android { @@ -29,7 +25,7 @@ android { buildTypes { getByName("release") { isMinifyEnabled = true - proguardFiles("proguard-rules.pro") + proguardFiles("proguard-android.txt", "proguard-rules.pro") consumerProguardFiles("proguard-rules.pro") } @@ -37,8 +33,4 @@ android { isMinifyEnabled = false } } -} - -kotlin { - configurePlatformTargets() } \ No newline at end of file diff --git a/android_kmp/build-logic/src/main/java/com.codandotv.application.gradle.kts b/android_kmp/build-logic/src/main/java/com.codandotv.application.gradle.kts index 8db9d38..8dbb4e3 100644 --- a/android_kmp/build-logic/src/main/java/com.codandotv.application.gradle.kts +++ b/android_kmp/build-logic/src/main/java/com.codandotv.application.gradle.kts @@ -1,5 +1,8 @@ @file:Suppress("UnstableApiUsage") +import Config.jvmTargetTool +import Config.jvmTargetValue +import Config.jvmTargetVersion import extensions.setupAndroidDefaultConfig import extensions.setupCompileOptions import extensions.setupPackingOptions @@ -30,9 +33,14 @@ android { versionName = Config.versionName multiDexEnabled = true } + + kotlin { + jvmToolchain(jvmTargetTool) + } + compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = jvmTargetVersion + targetCompatibility = jvmTargetVersion } android { diff --git a/android_kmp/build-logic/src/main/java/com.codandotv.kmp-library.gradle.kts b/android_kmp/build-logic/src/main/java/com.codandotv.kmp-library.gradle.kts new file mode 100644 index 0000000..bf4a136 --- /dev/null +++ b/android_kmp/build-logic/src/main/java/com.codandotv.kmp-library.gradle.kts @@ -0,0 +1,53 @@ +@file:Suppress("UnstableApiUsage") + +import Config.jvmTargetValue +import extensions.iosTarget +import extensions.setupAndroidDefaultConfig +import extensions.setupCompileOptions +import extensions.setupNameSpace +import extensions.setupPackingOptions + +plugins { + id("org.jetbrains.kotlin.multiplatform") + id("com.android.library") + id("org.jetbrains.kotlin.plugin.serialization") + id("kotlin-kapt") + id("kotlin-parcelize") +} + +kotlin { + androidTarget { + compilerOptions { + jvmTarget.set(jvmTargetValue) + freeCompilerArgs.add("-Xstring-concat=inline") + } + } + + iosTarget() +} + +android { + setupNameSpace(project) + + setupCompileOptions() + + setupPackingOptions() + + setupAndroidDefaultConfig() + defaultConfig.targetSdk = Config.targetSdkVersion + + buildTypes { + getByName("release") { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + consumerProguardFiles("proguard-rules.pro") + } + + getByName("debug") { + isMinifyEnabled = false + } + } +} \ No newline at end of file diff --git a/android_kmp/build-logic/src/main/java/com.codandotv.publish-android.gradle.kts b/android_kmp/build-logic/src/main/java/com.codandotv.publish-android.gradle.kts new file mode 100644 index 0000000..2e1a919 --- /dev/null +++ b/android_kmp/build-logic/src/main/java/com.codandotv.publish-android.gradle.kts @@ -0,0 +1,49 @@ +import com.vanniktech.maven.publish.AndroidMultiVariantLibrary +import com.vanniktech.maven.publish.SonatypeHost + +plugins{ + id("com.vanniktech.maven.publish.base") +} + +mavenPublishing { + publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) + signAllPublications() + + configure( + AndroidMultiVariantLibrary( + sourcesJar = true, + publishJavadocJar = true, + ) + ) + + coordinates( + project.property("GROUP_ID") as String, + project.property("ARTIFACT_ID") as String, + project.property("VERSION") as String + ) + + pom { + name.set(project.property("ARTIFACT_ID") as String) + description.set(project.property("ARTIFACT_ID") as String) + inceptionYear.set("2024") + url.set(project.property("POM_URL") as String) + + licenses { + license { + name.set(project.property("POM_LICENSE_NAME") as String) + url.set(project.property("POM_LICENSE_URL") as String) + } + } + scm { + connection.set("scm:git@github.com:CodandoTV/CraftD.git") + url.set("https://github.com/CodandoTV/CraftD.git") + } + developers { + developer { + id.set(project.property("POM_DEVELOPER_ID") as String) + name.set(project.property("POM_DEVELOPER_NAME") as String) + email.set(project.property("POM_DEVELOPER_EMAIL") as String) + } + } + } +} \ No newline at end of file diff --git a/android_kmp/build-logic/src/main/java/com.codandotv.publish.gradle.kts b/android_kmp/build-logic/src/main/java/com.codandotv.publish.gradle.kts index edfe32c..b3a8362 100644 --- a/android_kmp/build-logic/src/main/java/com.codandotv.publish.gradle.kts +++ b/android_kmp/build-logic/src/main/java/com.codandotv.publish.gradle.kts @@ -1,4 +1,3 @@ -import com.vanniktech.maven.publish.AndroidMultiVariantLibrary import com.vanniktech.maven.publish.SonatypeHost plugins{ @@ -9,13 +8,6 @@ mavenPublishing { publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) signAllPublications() - configure( - AndroidMultiVariantLibrary( - sourcesJar = true, - publishJavadocJar = true, - ) - ) - coordinates( project.property("GROUP_ID") as String, project.property("ARTIFACT_ID") as String, diff --git a/android_kmp/build-logic/src/main/java/extensions/CommonExtensions.kt b/android_kmp/build-logic/src/main/java/extensions/CommonExtensions.kt index 4e6b30d..ce6fe38 100644 --- a/android_kmp/build-logic/src/main/java/extensions/CommonExtensions.kt +++ b/android_kmp/build-logic/src/main/java/extensions/CommonExtensions.kt @@ -7,10 +7,9 @@ import com.android.build.api.dsl.CommonExtension import org.gradle.api.JavaVersion import org.gradle.api.Project import org.gradle.api.plugins.ExtensionAware -import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension -internal fun CommonExtension<*, *, *, *, *>.setupPackingOptions() { +internal fun CommonExtension<*, *, *, *, *,*>.setupPackingOptions() { packaging { resources { with(pickFirsts) { @@ -26,7 +25,7 @@ internal fun CommonExtension<*, *, *, *, *>.setupPackingOptions() { } } -internal fun CommonExtension<*, *, *, *, *>.setupAndroidDefaultConfig() { +internal fun CommonExtension<*, *, *, *, *,*>.setupAndroidDefaultConfig() { defaultConfig { compileSdk = Config.compileSdkVersion minSdk = Config.minSdkVersion @@ -36,37 +35,14 @@ internal fun CommonExtension<*, *, *, *, *>.setupAndroidDefaultConfig() { } } -internal fun CommonExtension<*, *, *, *, *>.setupCompileOptions() { +internal fun CommonExtension<*, *, *, *, *,*>.setupCompileOptions() { compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = Config.jvmTargetVersion + targetCompatibility = Config.jvmTargetVersion } } -internal fun KotlinMultiplatformExtension.configurePlatformTargets() { - -//Note: Keep when ios will be implemented -// listOf( -// iosX64(), -// iosArm64(), -// iosSimulatorArm64() -// ).forEach { iosTarget -> -// iosTarget.binaries.framework { -// baseName = Config.applicationId -// isStatic = true -// } -// } - - androidTarget { - compilations.all { - kotlinOptions { - jvmTarget = Config.jvmTarget - } - } - } -} - -internal fun CommonExtension<*, *, *, *, *>.setupNameSpace(project: Project) { +internal fun CommonExtension<*, *, *, *, *,*>.setupNameSpace(project: Project) { val moduleName = project.displayName .removePrefix("project ") .replace(":", ".") @@ -75,7 +51,3 @@ internal fun CommonExtension<*, *, *, *, *>.setupNameSpace(project: Project) { namespace = "${Config.applicationId}$moduleName" } - -private fun CommonExtension<*, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { - (this as ExtensionAware).extensions.configure("kotlinOptions", block) -} diff --git a/android_kmp/build-logic/src/main/java/extensions/KotlinMultiPlatformExt.kt b/android_kmp/build-logic/src/main/java/extensions/KotlinMultiPlatformExt.kt new file mode 100644 index 0000000..1d9d451 --- /dev/null +++ b/android_kmp/build-logic/src/main/java/extensions/KotlinMultiPlatformExt.kt @@ -0,0 +1,17 @@ +package extensions + +import Config +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension + +fun KotlinMultiplatformExtension.iosTarget() { + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = Config.appName + isStatic = false + } + } +} diff --git a/android_kmp/build.gradle.kts b/android_kmp/build.gradle.kts index ca7d830..791de69 100644 --- a/android_kmp/build.gradle.kts +++ b/android_kmp/build.gradle.kts @@ -1,18 +1,7 @@ plugins { alias(libs.plugins.kotlin.multiplatform) apply false alias(libs.plugins.jetbrains.compose) apply false -} - -buildscript { - repositories { - mavenCentral() - google() - gradlePluginPortal() - maven(url = "https://maven.pkg.jetbrains.space/public/p/compose/dev") - } - - dependencies { - classpath(libs.android.gradle.plugin) - classpath(libs.kotlin.gradle.plugin) - } + alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.kotlin.compose) apply false } \ No newline at end of file diff --git a/android_kmp/craftd-compose/.gitignore b/android_kmp/craftd-compose/.gitignore deleted file mode 100644 index 42afabf..0000000 --- a/android_kmp/craftd-compose/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/android_kmp/craftd-compose/build.gradle.kts b/android_kmp/craftd-compose/build.gradle.kts index 95e00e2..c71f863 100644 --- a/android_kmp/craftd-compose/build.gradle.kts +++ b/android_kmp/craftd-compose/build.gradle.kts @@ -1,51 +1,27 @@ plugins { - id("com.codandotv.android-library") - id("com.codandotv.publish") alias(libs.plugins.jetbrains.compose) + alias(libs.plugins.kotlin.compose) + id("com.codandotv.kmp-library") + id("com.codandotv.publish") } kotlin { + androidTarget { + publishLibraryVariants("release", "debug") + } sourceSets { androidMain.dependencies { - api(projects.craftdCore) implementation(libs.androidx.core) implementation(libs.androidx.appcompat) implementation(libs.google.material) - implementation(libs.kotlinx.collections.immutable) } commonMain.dependencies { + implementation(libs.kotlinx.serialization.json) + api(projects.craftdCore) implementation(compose.ui) implementation(compose.material3) + implementation(libs.kotlinx.collections.immutable) } } -} - -/** - * Compose metrics - * - * 1. First step is sync + build the project, this will generate the compose metrics; - * - * 2. Download [Mendable](https://github.com/jayasuryat/mendable) and run the following command: - * java -jar mendable.jar --scanRecursively -i /android_kmp/craftd-compose/build/compose_metrics -o /android_kmp/craftd-compose/reports -oName craftDComposeMetrics -eType html -rType all - * You can generate the compose metrics report using the following task: - * - * 3. Open the html file generated : ) - * - * To be able to see a beutiful report, the community recommends to use [Mendable](https://github.com/jayasuryat/mendable). - * - * You can check the metrics in the directory /build/compose_metrics. - * - */ -tasks.withType().all { - kotlinOptions.freeCompilerArgs += listOf( - "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + - project.buildDir.absolutePath + "/compose_metrics" - ) - kotlinOptions.freeCompilerArgs += listOf( - "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + - project.buildDir.absolutePath + "/compose_metrics" - ) } \ No newline at end of file diff --git a/android_kmp/craftd-compose/consumer-rules.pro b/android_kmp/craftd-compose/consumer-rules.pro deleted file mode 100644 index e69de29..0000000 diff --git a/android_kmp/craftd-compose/gradle.properties b/android_kmp/craftd-compose/gradle.properties index 3ef393c..0e7c851 100644 --- a/android_kmp/craftd-compose/gradle.properties +++ b/android_kmp/craftd-compose/gradle.properties @@ -1,2 +1,3 @@ +craftd.enableCompose=true ARTIFACT_ID=craftd-compose -VERSION=1.0.2 \ No newline at end of file +VERSION=1.1.0 diff --git a/android_kmp/craftd-compose/proguard-rules.pro b/android_kmp/craftd-compose/proguard-rules.pro deleted file mode 100644 index 481bb43..0000000 --- a/android_kmp/craftd-compose/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/android_kmp/craftd-compose/reports/crafDComposeMetrics_v2.html b/android_kmp/craftd-compose/reports/crafDComposeMetrics_v2.html deleted file mode 100644 index 3eaf212..0000000 --- a/android_kmp/craftd-compose/reports/crafDComposeMetrics_v2.html +++ /dev/null @@ -1,262 +0,0 @@ - - - Mendable - - - - - - - -

Mendable

-
1 module scanned
7 composables
7 restartable
7 skippable
0 not-skippable
100% stable

-
-
-
:craftd-compose (debug)
-
It's all good. All 7 restartable composables are skippable.
-
-
-


Made with <3 - Mendable

- - - diff --git a/android_kmp/craftd-compose/reports/craftDComposeMetrics.html b/android_kmp/craftd-compose/reports/craftDComposeMetrics.html deleted file mode 100644 index 6bf31b2..0000000 --- a/android_kmp/craftd-compose/reports/craftDComposeMetrics.html +++ /dev/null @@ -1,313 +0,0 @@ - - - Mendable - - - - - - - -

Mendable

-
1 module scanned
8 composables
8 restartable
3 skippable
5 not-skippable
38% stable

-
-
-
:craftd-compose (debug)
-
1. -
CraftDynamic Click to copy
-
-
@Composable
-fun CraftDynamic(
-   properties: List<SimpleProperties>, // Not stable
-   modifier: Modifier? = @static Companion,
-   dynamicBuilder: CraftDBuilderManager, // Not stable
-   onAction: Function1<ActionProperties, Unit>,
-){...}
-
-

2. -
craft Click to copy
-
-
@Composable
-fun craft(
-   model: SimpleProperties, // Not stable
-   listener: Function1<ActionProperties, Unit>,
-   stable <this>: CraftDButtonBuilder,
-){...}
-
-

3. -
craft Click to copy
-
-
@Composable
-fun craft(
-   model: SimpleProperties, // Not stable
-   listener: Function1<ActionProperties, Unit>,
-   stable <this>: CraftDCheckBoxBuilder,
-){...}
-
-

4. -
CraftDText Click to copy
-
-
@Composable
-fun CraftDText(
-   textProperties: TextProperties, // Not stable
-   modifier: Modifier? = @static Companion,
-   clickable: Function0<Unit>? = @static null,
-){...}
-
-

5. -
craft Click to copy
-
-
@Composable
-fun craft(
-   model: SimpleProperties, // Not stable
-   listener: Function1<ActionProperties, Unit>,
-   stable <this>: CraftDTextBuilder,
-){...}
-
-
-
-
-


Made with <3 - Mendable

- - - diff --git a/android_kmp/craftd-compose/src/androidMain/AndroidManifest.xml b/android_kmp/craftd-compose/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000..a861a9c --- /dev/null +++ b/android_kmp/craftd-compose/src/androidMain/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/HtmlPlatform.android.kt b/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/HtmlPlatform.android.kt new file mode 100644 index 0000000..0753796 --- /dev/null +++ b/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/HtmlPlatform.android.kt @@ -0,0 +1,7 @@ +package com.github.codandotv.craftd.compose + +import androidx.core.text.HtmlCompat + +actual fun parseHtmlToPlainText(html: String): String { + return HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_COMPACT).toString() +} \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/Platform.android.kt b/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/Platform.android.kt new file mode 100644 index 0000000..cc7a3c5 --- /dev/null +++ b/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/Platform.android.kt @@ -0,0 +1,7 @@ +package com.github.codandotv.craftd.compose + +import androidx.core.text.HtmlCompat + +actual fun parseHtmlToString(html: String): String { + return HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_COMPACT).toString() +} \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml b/android_kmp/craftd-compose/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/android_kmp/craftd-compose/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/androidMain/res/drawable/ic_launcher_background.xml b/android_kmp/craftd-compose/src/androidMain/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..e93e11a --- /dev/null +++ b/android_kmp/craftd-compose/src/androidMain/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml b/android_kmp/craftd-compose/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/android_kmp/craftd-compose/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android_kmp/craftd-compose/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/android_kmp/craftd-compose/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-hdpi/ic_launcher.png b/android_kmp/craftd-compose/src/androidMain/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a571e60 Binary files /dev/null and b/android_kmp/craftd-compose/src/androidMain/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png b/android_kmp/craftd-compose/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..61da551 Binary files /dev/null and b/android_kmp/craftd-compose/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-mdpi/ic_launcher.png b/android_kmp/craftd-compose/src/androidMain/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..c41dd28 Binary files /dev/null and b/android_kmp/craftd-compose/src/androidMain/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png b/android_kmp/craftd-compose/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..db5080a Binary files /dev/null and b/android_kmp/craftd-compose/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-xhdpi/ic_launcher.png b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6dba46d Binary files /dev/null and b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..da31a87 Binary files /dev/null and b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..15ac681 Binary files /dev/null and b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..b216f2d Binary files /dev/null and b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..f25a419 Binary files /dev/null and b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..e96783c Binary files /dev/null and b/android_kmp/craftd-compose/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/android_kmp/craftd-compose/src/androidMain/res/values/strings.xml b/android_kmp/craftd-compose/src/androidMain/res/values/strings.xml new file mode 100644 index 0000000..f690955 --- /dev/null +++ b/android_kmp/craftd-compose/src/androidMain/res/values/strings.xml @@ -0,0 +1,3 @@ + + craftd + \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/commonMain/composeResources/drawable/compose-multiplatform.xml b/android_kmp/craftd-compose/src/commonMain/composeResources/drawable/compose-multiplatform.xml new file mode 100644 index 0000000..1ffc948 --- /dev/null +++ b/android_kmp/craftd-compose/src/commonMain/composeResources/drawable/compose-multiplatform.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/HtmlPlatform.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/HtmlPlatform.kt new file mode 100644 index 0000000..bcd616f --- /dev/null +++ b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/HtmlPlatform.kt @@ -0,0 +1,3 @@ +package com.github.codandotv.craftd.compose + +expect fun parseHtmlToPlainText(html: String): String diff --git a/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/Platform.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/Platform.kt new file mode 100644 index 0000000..deef859 --- /dev/null +++ b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/Platform.kt @@ -0,0 +1,3 @@ +package com.github.codandotv.craftd.compose + +expect fun parseHtmlToString(html: String): String diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/builder/CraftDBuilder.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/builder/CraftDBuilder.kt similarity index 100% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/builder/CraftDBuilder.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/builder/CraftDBuilder.kt diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/builder/CraftDBuilderManager.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/builder/CraftDBuilderManager.kt similarity index 100% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/builder/CraftDBuilderManager.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/builder/CraftDBuilderManager.kt diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/extensions/UtilsCompose.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/extensions/UtilsCompose.kt similarity index 68% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/extensions/UtilsCompose.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/extensions/UtilsCompose.kt index fe07a7f..3930101 100644 --- a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/extensions/UtilsCompose.kt +++ b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/extensions/UtilsCompose.kt @@ -36,9 +36,25 @@ fun CraftDAlign?.toAlignmentCompose() : Alignment.Vertical = when (this) { } fun String?.parseColorCompose(): Color { - return try { - Color(android.graphics.Color.parseColor(this)) - } catch (ex: Exception) { - Color.Unspecified - } -} \ No newline at end of file + return runCatching { + val clean = this!!.removePrefix("#") + + val argb = when (clean.length) { + 6 -> "FF$clean" // Add alpha if missing + 8 -> clean + else -> throw IllegalArgumentException("Invalid hex: $this") + } + + val a = argb.substring(0, 2).toInt(16) + val r = argb.substring(2, 4).toInt(16) + val g = argb.substring(4, 6).toInt(16) + val b = argb.substring(6, 8).toInt(16) + + Color( + alpha = a, + red = r, + green = g, + blue = b + ) + }.getOrDefault(Color.Unspecified) +} diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/CraftDynamic.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/CraftDynamic.kt similarity index 100% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/CraftDynamic.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/CraftDynamic.kt diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/button/CraftDButton.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/button/CraftDButton.kt similarity index 100% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/button/CraftDButton.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/button/CraftDButton.kt diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/button/CraftDButtonBuilder.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/button/CraftDButtonBuilder.kt similarity index 70% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/button/CraftDButtonBuilder.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/button/CraftDButtonBuilder.kt index 7413a66..7439544 100644 --- a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/button/CraftDButtonBuilder.kt +++ b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/button/CraftDButtonBuilder.kt @@ -1,7 +1,7 @@ package com.github.codandotv.craftd.compose.ui.button import androidx.compose.runtime.Composable -import com.github.codandotv.craftd.androidcore.data.convertToVO +import com.github.codandotv.craftd.androidcore.data.convertToElement import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties import com.github.codandotv.craftd.androidcore.data.model.button.ButtonProperties import com.github.codandotv.craftd.androidcore.presentation.CraftDComponentKey @@ -13,9 +13,11 @@ class CraftDButtonBuilder( ) : CraftDBuilder { @Composable override fun craft(model: SimpleProperties, listener: CraftDViewListener) { - val buttonProperties = model.value.convertToVO() - CraftDButton(buttonProperties) { - buttonProperties.actionProperties?.let { listener.invoke(it) } + val buttonProperties = model.value.convertToElement() + buttonProperties?.let { + CraftDButton(it) { + buttonProperties.actionProperties?.let { listener.invoke(it) } + } } } } \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/checkbox/CraftDCheckBox.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/checkbox/CraftDCheckBox.kt similarity index 100% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/checkbox/CraftDCheckBox.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/checkbox/CraftDCheckBox.kt diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/checkbox/CraftDCheckBoxBuilder.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/checkbox/CraftDCheckBoxBuilder.kt similarity index 69% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/checkbox/CraftDCheckBoxBuilder.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/checkbox/CraftDCheckBoxBuilder.kt index 037ed51..e75059d 100644 --- a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/checkbox/CraftDCheckBoxBuilder.kt +++ b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/checkbox/CraftDCheckBoxBuilder.kt @@ -1,7 +1,7 @@ package com.github.codandotv.craftd.compose.ui.checkbox import androidx.compose.runtime.Composable -import com.github.codandotv.craftd.androidcore.data.convertToVO +import com.github.codandotv.craftd.androidcore.data.convertToElement import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties import com.github.codandotv.craftd.androidcore.data.model.checkbox.CheckBoxProperties import com.github.codandotv.craftd.androidcore.presentation.CraftDComponentKey @@ -14,9 +14,11 @@ class CraftDCheckBoxBuilder( CraftDBuilder { @Composable override fun craft(model: SimpleProperties, listener: CraftDViewListener) { - val checkBoxProperties = model.value.convertToVO() - CraftDCheckBox(checkBoxProperties) { - checkBoxProperties.actionProperties?.let { listener.invoke(it) } + val checkBoxProperties = model.value.convertToElement() + checkBoxProperties?.let { + CraftDCheckBox(it) { + checkBoxProperties.actionProperties?.let { listener.invoke(it) } + } } } } \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/empty/CraftDEmptyBuilder.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/empty/CraftDEmptyBuilder.kt similarity index 100% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/empty/CraftDEmptyBuilder.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/empty/CraftDEmptyBuilder.kt diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDText.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDText.kt similarity index 91% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDText.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDText.kt index 4568d5a..98a2690 100644 --- a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDText.kt +++ b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDText.kt @@ -9,12 +9,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.sp -import androidx.core.text.HtmlCompat import com.github.codandotv.craftd.androidcore.data.model.text.TextProperties import com.github.codandotv.craftd.androidcore.extensions.empty import com.github.codandotv.craftd.compose.extensions.parseColorCompose import com.github.codandotv.craftd.compose.extensions.toAlignCompose import com.github.codandotv.craftd.compose.extensions.toTextStyle +import com.github.codandotv.craftd.compose.parseHtmlToPlainText @Composable fun CraftDText( @@ -38,9 +38,7 @@ fun CraftDText( fontSize = textProperties.textSize?.toFloat()?.sp ?: TextUnit.Unspecified, ), text = textProperties.textHtml?.let { html -> - HtmlCompat.fromHtml( - html, HtmlCompat.FROM_HTML_MODE_COMPACT - ).toString() + parseHtmlToPlainText(html) } ?: textProperties.textWithRightCaps(), color = textProperties.textColorHex?.parseColorCompose() ?: Color.Unspecified, textAlign = textProperties.align.toAlignCompose(), diff --git a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDTextBuilder.kt b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDTextBuilder.kt similarity index 69% rename from android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDTextBuilder.kt rename to android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDTextBuilder.kt index b077733..614eb55 100644 --- a/android_kmp/craftd-compose/src/androidMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDTextBuilder.kt +++ b/android_kmp/craftd-compose/src/commonMain/kotlin/com/github/codandotv/craftd/compose/ui/text/CraftDTextBuilder.kt @@ -1,7 +1,7 @@ package com.github.codandotv.craftd.compose.ui.text import androidx.compose.runtime.Composable -import com.github.codandotv.craftd.androidcore.data.convertToVO +import com.github.codandotv.craftd.androidcore.data.convertToElement import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties import com.github.codandotv.craftd.androidcore.data.model.text.TextProperties import com.github.codandotv.craftd.androidcore.presentation.CraftDComponentKey @@ -13,9 +13,11 @@ class CraftDTextBuilder( ) : CraftDBuilder{ @Composable override fun craft(model: SimpleProperties, listener: CraftDViewListener) { - val textProperties = model.value.convertToVO() - CraftDText(textProperties = textProperties) { - textProperties.actionProperties?.let { listener.invoke(it) } + val textProperties = model.value.convertToElement() + textProperties?.let { + CraftDText(textProperties = it) { + textProperties.actionProperties?.let { listener.invoke(it) } + } } } } \ No newline at end of file diff --git a/android_kmp/craftd-compose/src/iosMain/kotlin/com/github/codandotv/craftd/compose/HtmlPlatform.ios.kt b/android_kmp/craftd-compose/src/iosMain/kotlin/com/github/codandotv/craftd/compose/HtmlPlatform.ios.kt new file mode 100644 index 0000000..db6a883 --- /dev/null +++ b/android_kmp/craftd-compose/src/iosMain/kotlin/com/github/codandotv/craftd/compose/HtmlPlatform.ios.kt @@ -0,0 +1,25 @@ +package com.github.codandotv.craftd.compose + +private fun unescapeBasicEntities(s: String): String = + s.replace(" ", " ") + .replace("&", "&") + .replace("<", "<") + .replace(">", ">") + .replace(""", "\"") + .replace("'", "'") + +actual fun parseHtmlToPlainText(html: String): String { + val withBreaks = html + .replace(Regex("(?i)"), "\n") + .replace(Regex("(?i)

"), "\n") + + val noTags = withBreaks.replace(Regex("<[^>]+>"), "") // remove tags + + // Colapsa mĂșltiplas quebras/espaços e desescapa entidades bĂĄsicas + return unescapeBasicEntities( + noTags + .replace(Regex("[ \\t\\x0B\\f\\r]+"), " ") + .replace(Regex("\\n{3,}"), "\n\n") + .trim() + ) +} diff --git a/android_kmp/craftd-compose/src/iosMain/kotlin/com/github/codandotv/craftd/compose/Platform.ios.kt b/android_kmp/craftd-compose/src/iosMain/kotlin/com/github/codandotv/craftd/compose/Platform.ios.kt new file mode 100644 index 0000000..3d4f58e --- /dev/null +++ b/android_kmp/craftd-compose/src/iosMain/kotlin/com/github/codandotv/craftd/compose/Platform.ios.kt @@ -0,0 +1,5 @@ +package com.github.codandotv.craftd.compose + +actual fun parseHtmlToString(html: String): String { + return html +} diff --git a/android_kmp/craftd-core/build.gradle.kts b/android_kmp/craftd-core/build.gradle.kts index 425a3d3..70fc7b5 100644 --- a/android_kmp/craftd-core/build.gradle.kts +++ b/android_kmp/craftd-core/build.gradle.kts @@ -1,17 +1,29 @@ plugins { - id("com.codandotv.android-library") + id("com.codandotv.kmp-library") + alias(libs.plugins.jetbrains.compose) + alias(libs.plugins.kotlin.compose) id("com.codandotv.publish") } kotlin { + androidTarget { + publishLibraryVariants("release", "debug") + } sourceSets { androidMain.dependencies { - implementation(libs.compose.lifecycle) implementation(libs.androidx.core) implementation(libs.androidx.appcompat) implementation(libs.google.material) implementation(libs.fasterxml.jackson) implementation(libs.fasterxml.jackson.databind) } + + commonMain.dependencies { + api(libs.kotlinx.serialization.json) + implementation(libs.kotlinx.coroutines.core) + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + } } } \ No newline at end of file diff --git a/android_kmp/craftd-core/gradle.properties b/android_kmp/craftd-core/gradle.properties index e4c9439..a8961e0 100644 --- a/android_kmp/craftd-core/gradle.properties +++ b/android_kmp/craftd-core/gradle.properties @@ -1,2 +1,2 @@ ARTIFACT_ID=craftd-core -VERSION=1.0.2 \ No newline at end of file +VERSION=1.1.0 \ No newline at end of file diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDSimplePropertiesDiffCallback.kt b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/CraftDSimplePropertiesDiffCallback.kt similarity index 94% rename from android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDSimplePropertiesDiffCallback.kt rename to android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/CraftDSimplePropertiesDiffCallback.kt index 2656152..aa94beb 100644 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDSimplePropertiesDiffCallback.kt +++ b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/CraftDSimplePropertiesDiffCallback.kt @@ -1,4 +1,4 @@ -package com.github.codandotv.craftd.androidcore.presentation +package com.github.codandotv.craftd.androidcore import android.annotation.SuppressLint import androidx.recyclerview.widget.DiffUtil diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/ViewMapperVo.kt b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/ViewMapperVo.kt new file mode 100644 index 0000000..820cb8a --- /dev/null +++ b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/ViewMapperVo.kt @@ -0,0 +1,7 @@ +package com.github.codandotv.craftd.androidcore.data + +import com.fasterxml.jackson.databind.ObjectMapper + + +inline fun Any?.convertToVO(): T = + ObjectMapper().convertValue(this, T::class.java) as T diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/ActionProperties.kt b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/ActionProperties.kt deleted file mode 100644 index 6bc209b..0000000 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/ActionProperties.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.github.codandotv.craftd.androidcore.data.model.action - -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.Stable -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonProperty - -@Stable -@Immutable -@JsonIgnoreProperties(ignoreUnknown = true) -data class ActionProperties ( - @JsonProperty("deeplink") - val deeplink : String?, - - @JsonProperty("actionData") - val actionData: Any?, - - @JsonProperty("analytics") - val analytics: AnalyticsProperties?, -) \ No newline at end of file diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimpleProperties.kt b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimpleProperties.kt deleted file mode 100644 index bfcd239..0000000 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimpleProperties.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.github.codandotv.craftd.androidcore.data.model.base - -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.Stable -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonProperty - -@Immutable -@Stable -@JsonIgnoreProperties(ignoreUnknown = true) -data class SimpleProperties( - @JsonProperty("key") val key: String = "", - @JsonProperty("value") val value: Any? = null -) diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimplePropertiesResponse.kt b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimplePropertiesResponse.kt deleted file mode 100644 index 80ed816..0000000 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimplePropertiesResponse.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.github.codandotv.craftd.androidcore.data.model.base - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonProperty - -@JsonIgnoreProperties(ignoreUnknown = true) -data class SimplePropertiesResponse( - @JsonProperty("key") val key: String = "", - @JsonProperty("value") val value: Any? = null -) - -@JsonIgnoreProperties(ignoreUnknown = true) -data class DataSimplePropertiesResponse( - val data : List -) \ No newline at end of file diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/button/ButtonProperties.kt b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/button/ButtonProperties.kt deleted file mode 100644 index 3104586..0000000 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/button/ButtonProperties.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.codandotv.craftd.androidcore.data.model.button - -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.Stable -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonProperty -import com.github.codandotv.craftd.androidcore.data.model.action.ActionProperties -import com.github.codandotv.craftd.androidcore.domain.CraftDAlign - -@JsonIgnoreProperties(ignoreUnknown = true) -@Immutable -@Stable -data class ButtonProperties( - @JsonProperty("text") val text: String? = null, - @JsonProperty("textColorHex") val textColorHex: String? = null, - @JsonProperty("align") val align: CraftDAlign? = null, - @JsonProperty("textAlign") val textAlign: CraftDAlign? = null, - @JsonProperty("textSize") val textSize: String? = null, - @JsonProperty("textAllCaps") val textAllCaps: Boolean? = false, - @JsonProperty("fillMaxSize") val fillMaxSize: Boolean? = false, - @JsonProperty("backgroundHex") val backgroundHex: String? = null, - @JsonProperty("actionProperties") var actionProperties: ActionProperties? = null, -) diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/CheckBoxProperties.kt b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/CheckBoxProperties.kt deleted file mode 100644 index 1c40d59..0000000 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/CheckBoxProperties.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.codandotv.craftd.androidcore.data.model.checkbox - -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.Stable -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonProperty -import com.github.codandotv.craftd.androidcore.data.model.action.ActionProperties -import com.github.codandotv.craftd.androidcore.domain.CraftDAlign - -@JsonIgnoreProperties(ignoreUnknown = true) -@Immutable -@Stable -data class CheckBoxProperties( - @JsonProperty("text") val text: String? = null, - @JsonProperty("align") val align: CraftDAlign? = null, - @JsonProperty("textAlign") val textAlign: CraftDAlign? = null, - @JsonProperty("enable") val enable: Boolean? = false, - @JsonProperty("hasItRightText") val hasItRightText: Boolean? = false, - @JsonProperty("actionProperties") var actionProperties: ActionProperties? = null, - @JsonProperty("style") var styleProperties: StyleProperties? = null, -) diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/StyleProperties.kt b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/StyleProperties.kt deleted file mode 100644 index 6426722..0000000 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/StyleProperties.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.github.codandotv.craftd.androidcore.data.model.checkbox - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonProperty - -@JsonIgnoreProperties(ignoreUnknown = true) -data class StyleProperties( - @JsonProperty("checkedColorHex") - val checkedColor: String?, - @JsonProperty("uncheckedColorHex") - val uncheckedColor: String? -) \ No newline at end of file diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/text/TextProperties.kt b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/text/TextProperties.kt deleted file mode 100644 index 2dac422..0000000 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/text/TextProperties.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.github.codandotv.craftd.androidcore.data.model.text - -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.Stable -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonProperty -import com.github.codandotv.craftd.androidcore.data.model.action.ActionProperties -import com.github.codandotv.craftd.androidcore.domain.CraftDAlign -import com.github.codandotv.craftd.androidcore.domain.CraftDTextStyle - -@Stable -@Immutable -@JsonIgnoreProperties(ignoreUnknown = true) -data class TextProperties( - @JsonProperty("text") val text: String? = null, - @JsonProperty("textColorHex") val textColorHex: String? = null, - @JsonProperty("align") val align: CraftDAlign? = null, - @JsonProperty("textSize") val textSize: String? = null, - @JsonProperty("backgroundHex") val backgroundHex: String? = null, - @JsonProperty("textStyle") val textStyle: CraftDTextStyle? = null, - @JsonProperty("textAllCaps") val textAllCaps: Boolean? = false, - @JsonProperty("actionProperties") var actionProperties: ActionProperties? = null, - @JsonProperty("textHtml") val textHtml: String? = null, -) - diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDViewListener.kt b/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDViewListener.kt deleted file mode 100644 index b191c0b..0000000 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDViewListener.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.github.codandotv.craftd.androidcore.presentation - -import com.github.codandotv.craftd.androidcore.data.model.action.ActionProperties - -typealias CraftDViewListener = ((ActionProperties) -> Unit) diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/ViewMapper.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/ViewMapper.kt similarity index 54% rename from android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/ViewMapper.kt rename to android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/ViewMapper.kt index c104a28..e9acd86 100644 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/ViewMapper.kt +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/ViewMapper.kt @@ -1,11 +1,19 @@ package com.github.codandotv.craftd.androidcore.data -import com.fasterxml.jackson.databind.ObjectMapper import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties import com.github.codandotv.craftd.androidcore.data.model.base.SimplePropertiesResponse +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.decodeFromJsonElement -inline fun Any?.convertToVO(): T = - ObjectMapper().convertValue(this, T::class.java) as T +inline fun JsonElement?.convertToElement(): T? { + if (this == null) return null + return try { + Json { ignoreUnknownKeys = true }.decodeFromJsonElement(this) + } catch (e: Exception) { + null + } +} fun List.toListSimpleProperties() = this.map { it.toSimpleProperties() diff --git a/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/ActionProperties.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/ActionProperties.kt new file mode 100644 index 0000000..f43974c --- /dev/null +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/ActionProperties.kt @@ -0,0 +1,21 @@ +package com.github.codandotv.craftd.androidcore.data.model.action + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonElement + +@Stable +@Immutable +@Serializable +data class ActionProperties( + @SerialName("deeplink") + val deeplink: String? = null, + + @SerialName("actionData") + val actionData: JsonElement? = null, // Substitui Any? para ser compatĂ­vel com JSON dinĂąmico + + @SerialName("analytics") + val analytics: AnalyticsProperties? = null, +) diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/AnalyticsProperties.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/AnalyticsProperties.kt similarity index 55% rename from android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/AnalyticsProperties.kt rename to android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/AnalyticsProperties.kt index f6589d5..cd45285 100644 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/AnalyticsProperties.kt +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/action/AnalyticsProperties.kt @@ -2,22 +2,22 @@ package com.github.codandotv.craftd.androidcore.data.model.action import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonProperty +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable @Stable @Immutable -@JsonIgnoreProperties(ignoreUnknown = true) +@Serializable data class AnalyticsProperties( - @JsonProperty("category") + @SerialName("category") val category: String? = null, - @JsonProperty("action") + @SerialName("action") val action: String? = null, - @JsonProperty("label") + @SerialName("label") val label: String? = null, - @JsonProperty("track") + @SerialName("track") val track: String? = null, ) diff --git a/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimpleProperties.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimpleProperties.kt new file mode 100644 index 0000000..8535b7b --- /dev/null +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimpleProperties.kt @@ -0,0 +1,15 @@ +package com.github.codandotv.craftd.androidcore.data.model.base + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonElement + +@Immutable +@Stable +@Serializable +data class SimpleProperties( + @SerialName("key") val key: String = "", + @SerialName("value") val value: JsonElement? = null +) diff --git a/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimplePropertiesResponse.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimplePropertiesResponse.kt new file mode 100644 index 0000000..8ecc7d2 --- /dev/null +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/base/SimplePropertiesResponse.kt @@ -0,0 +1,16 @@ +package com.github.codandotv.craftd.androidcore.data.model.base + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonElement + +@Serializable +data class SimplePropertiesResponse( + @SerialName("key") val key: String = "", + @SerialName("value") val value: JsonElement? = null +) + +@Serializable +data class DataSimplePropertiesResponse( + val data: List +) diff --git a/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/button/ButtonProperties.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/button/ButtonProperties.kt new file mode 100644 index 0000000..7fc2bd4 --- /dev/null +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/button/ButtonProperties.kt @@ -0,0 +1,23 @@ +package com.github.codandotv.craftd.androidcore.data.model.button + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable +import com.github.codandotv.craftd.androidcore.data.model.action.ActionProperties +import com.github.codandotv.craftd.androidcore.domain.CraftDAlign +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@Immutable +@Stable +data class ButtonProperties( + @SerialName("text") val text: String? = null, + @SerialName("textColorHex") val textColorHex: String? = null, + @SerialName("align") val align: CraftDAlign? = null, + @SerialName("textAlign") val textAlign: CraftDAlign? = null, + @SerialName("textSize") val textSize: String? = null, + @SerialName("textAllCaps") val textAllCaps: Boolean? = false, + @SerialName("fillMaxSize") val fillMaxSize: Boolean? = false, + @SerialName("backgroundHex") val backgroundHex: String? = null, + @SerialName("actionProperties") var actionProperties: ActionProperties? = null, +) diff --git a/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/CheckBoxProperties.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/CheckBoxProperties.kt new file mode 100644 index 0000000..31bf49d --- /dev/null +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/CheckBoxProperties.kt @@ -0,0 +1,34 @@ +package com.github.codandotv.craftd.androidcore.data.model.checkbox + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable +import com.github.codandotv.craftd.androidcore.data.model.action.ActionProperties +import com.github.codandotv.craftd.androidcore.domain.CraftDAlign +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Stable +@Immutable +@Serializable +data class CheckBoxProperties( + @SerialName("text") + val text: String? = null, + + @SerialName("align") + val align: CraftDAlign? = null, + + @SerialName("textAlign") + val textAlign: CraftDAlign? = null, + + @SerialName("enable") + val enable: Boolean? = false, + + @SerialName("hasItRightText") + val hasItRightText: Boolean? = false, + + @SerialName("actionProperties") + var actionProperties: ActionProperties? = null, + + @SerialName("style") + var styleProperties: StyleProperties? = null, +) diff --git a/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/StyleProperties.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/StyleProperties.kt new file mode 100644 index 0000000..6f9cd8c --- /dev/null +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/checkbox/StyleProperties.kt @@ -0,0 +1,13 @@ +package com.github.codandotv.craftd.androidcore.data.model.checkbox + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class StyleProperties( + @SerialName("checkedColorHex") + val checkedColor: String? = null, + + @SerialName("uncheckedColorHex") + val uncheckedColor: String? = null +) diff --git a/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/text/TextProperties.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/text/TextProperties.kt new file mode 100644 index 0000000..c08bacb --- /dev/null +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/data/model/text/TextProperties.kt @@ -0,0 +1,24 @@ +package com.github.codandotv.craftd.androidcore.data.model.text + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import com.github.codandotv.craftd.androidcore.data.model.action.ActionProperties +import com.github.codandotv.craftd.androidcore.domain.CraftDAlign +import com.github.codandotv.craftd.androidcore.domain.CraftDTextStyle + +@Stable +@Immutable +@Serializable +data class TextProperties( + @SerialName("text") val text: String? = null, + @SerialName("textColorHex") val textColorHex: String? = null, + @SerialName("align") val align: CraftDAlign? = null, + @SerialName("textSize") val textSize: String? = null, + @SerialName("backgroundHex") val backgroundHex: String? = null, + @SerialName("textStyle") val textStyle: CraftDTextStyle? = null, + @SerialName("textAllCaps") val textAllCaps: Boolean? = false, + @SerialName("actionProperties") var actionProperties: ActionProperties? = null, + @SerialName("textHtml") val textHtml: String? = null, +) diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/domain/CraftDAlign.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/domain/CraftDAlign.kt similarity index 100% rename from android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/domain/CraftDAlign.kt rename to android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/domain/CraftDAlign.kt diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/domain/CraftDTextStyle.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/domain/CraftDTextStyle.kt similarity index 100% rename from android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/domain/CraftDTextStyle.kt rename to android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/domain/CraftDTextStyle.kt diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/extensions/StringExtensions.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/extensions/StringExtensions.kt similarity index 100% rename from android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/extensions/StringExtensions.kt rename to android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/extensions/StringExtensions.kt diff --git a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDComponentKey.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDComponentKey.kt similarity index 86% rename from android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDComponentKey.kt rename to android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDComponentKey.kt index f23cf10..92e7529 100644 --- a/android_kmp/craftd-core/src/androidMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDComponentKey.kt +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDComponentKey.kt @@ -1,11 +1,10 @@ package com.github.codandotv.craftd.androidcore.presentation - enum class CraftDComponentKey(val key: String) { TEXT_VIEW_COMPONENT("${CRAFT_D}TextView"), BUTTON_COMPONENT("${CRAFT_D}Button"), CHECK_BOX_COMPONENT("${CRAFT_D}CheckBox"), } -internal const val CRAFT_D = "CraftD" +internal const val CRAFT_D = "CraftD" \ No newline at end of file diff --git a/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDViewListener.kt b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDViewListener.kt new file mode 100644 index 0000000..7ee6400 --- /dev/null +++ b/android_kmp/craftd-core/src/commonMain/kotlin/com/github/codandotv/craftd/androidcore/presentation/CraftDViewListener.kt @@ -0,0 +1,3 @@ +package com.github.codandotv.craftd.androidcore.presentation + +typealias CraftDViewListener = ((com.github.codandotv.craftd.androidcore.data.model.action.ActionProperties) -> Unit) diff --git a/android_kmp/craftd-xml/build.gradle.kts b/android_kmp/craftd-xml/build.gradle.kts index 06f1705..332991a 100644 --- a/android_kmp/craftd-xml/build.gradle.kts +++ b/android_kmp/craftd-xml/build.gradle.kts @@ -6,16 +6,12 @@ android{ plugins { id("com.codandotv.android-library") - id("com.codandotv.publish") + id("com.codandotv.publish-android") } -kotlin { - sourceSets { - androidMain.dependencies { - api(projects.craftdCore) - implementation(libs.androidx.core) - implementation(libs.androidx.appcompat) - implementation(libs.google.material) - } - } +dependencies { + api(projects.craftdCore) + implementation(libs.androidx.core) + implementation(libs.androidx.appcompat) + implementation(libs.google.material) } \ No newline at end of file diff --git a/android_kmp/craftd-xml/gradle.properties b/android_kmp/craftd-xml/gradle.properties index 9f7dd7f..37ce44b 100644 --- a/android_kmp/craftd-xml/gradle.properties +++ b/android_kmp/craftd-xml/gradle.properties @@ -1,2 +1,2 @@ ARTIFACT_ID=craftd-xml -VERSION=1.0.2 \ No newline at end of file +VERSION=1.1.0 \ No newline at end of file diff --git a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/builder/CraftDBuilderManager.kt b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/builder/CraftDBuilderManager.kt similarity index 100% rename from android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/builder/CraftDBuilderManager.kt rename to android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/builder/CraftDBuilderManager.kt diff --git a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/CraftDEmptyViewHolder.kt b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/CraftDEmptyViewHolder.kt similarity index 100% rename from android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/CraftDEmptyViewHolder.kt rename to android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/CraftDEmptyViewHolder.kt diff --git a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/CraftDView.kt b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/CraftDView.kt similarity index 100% rename from android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/CraftDView.kt rename to android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/CraftDView.kt diff --git a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/CraftDViewAdapter.kt b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/CraftDViewAdapter.kt similarity index 97% rename from android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/CraftDViewAdapter.kt rename to android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/CraftDViewAdapter.kt index d2a4280..aa951b8 100644 --- a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/CraftDViewAdapter.kt +++ b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/CraftDViewAdapter.kt @@ -6,8 +6,8 @@ import android.widget.FrameLayout import androidx.core.util.forEach import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.RecyclerView +import com.github.codandotv.craftd.androidcore.CraftDSimplePropertiesItemCallback import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties -import com.github.codandotv.craftd.androidcore.presentation.CraftDSimplePropertiesItemCallback /** * The creation I use with base/inspiration tree papers : diff --git a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/CraftDViewRenderer.kt b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/CraftDViewRenderer.kt similarity index 100% rename from android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/CraftDViewRenderer.kt rename to android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/CraftDViewRenderer.kt diff --git a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/button/CraftDButtonComponent.kt b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/button/CraftDButtonComponent.kt similarity index 100% rename from android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/button/CraftDButtonComponent.kt rename to android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/button/CraftDButtonComponent.kt diff --git a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/button/CraftDButtonComponentRender.kt b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/button/CraftDButtonComponentRender.kt similarity index 83% rename from android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/button/CraftDButtonComponentRender.kt rename to android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/button/CraftDButtonComponentRender.kt index 0a4bdde..59c63a5 100644 --- a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/button/CraftDButtonComponentRender.kt +++ b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/button/CraftDButtonComponentRender.kt @@ -3,6 +3,7 @@ package com.github.codandotv.craftd.xml.ui.button import android.graphics.Color.parseColor import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView +import com.github.codandotv.craftd.androidcore.data.convertToElement import com.github.codandotv.craftd.androidcore.data.convertToVO import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties import com.github.codandotv.craftd.androidcore.data.model.button.ButtonProperties @@ -18,10 +19,10 @@ class ButtonComponentRender(override var onClickListener: CraftDViewListener?) : inner class ButtonHolder(val button: CraftDButtonComponent) : RecyclerView.ViewHolder(button) override fun bindView(model: SimpleProperties, holder: ButtonHolder, position: Int) { - val buttonProperties = model.value.convertToVO() + val buttonProperties = model.value.convertToElement() - holder.button.setProperties(buttonProperties) - buttonProperties.actionProperties?.let { actionProperties -> + buttonProperties?.let { holder.button.setProperties(it) } + buttonProperties?.actionProperties?.let { actionProperties -> holder.button.setOnClickListener { onClickListener?.invoke(actionProperties) } diff --git a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/text/CraftDTextViewComponent.kt b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/text/CraftDTextViewComponent.kt similarity index 100% rename from android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/text/CraftDTextViewComponent.kt rename to android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/text/CraftDTextViewComponent.kt diff --git a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/text/CraftDTextViewComponentRender.kt b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/text/CraftDTextViewComponentRender.kt similarity index 83% rename from android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/text/CraftDTextViewComponentRender.kt rename to android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/text/CraftDTextViewComponentRender.kt index 70908ee..1d42bfd 100644 --- a/android_kmp/craftd-xml/src/androidMain/kotlin/com/github/codandotv/craftd/xml/ui/text/CraftDTextViewComponentRender.kt +++ b/android_kmp/craftd-xml/src/main/kotlin/com/github/codandotv/craftd/xml/ui/text/CraftDTextViewComponentRender.kt @@ -2,6 +2,7 @@ package com.github.codandotv.craftd.xml.ui.text import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView +import com.github.codandotv.craftd.androidcore.data.convertToElement import com.github.codandotv.craftd.androidcore.data.convertToVO import com.github.codandotv.craftd.androidcore.data.model.base.SimpleProperties import com.github.codandotv.craftd.androidcore.data.model.text.TextProperties @@ -17,10 +18,10 @@ class CraftDTextViewComponentRender(override var onClickListener: CraftDViewList inner class TextViewHolder(val textView: CraftDTextViewComponent) : RecyclerView.ViewHolder(textView) override fun bindView(model: SimpleProperties, holder: TextViewHolder, position: Int) { - val textProperties = model.value.convertToVO() - holder.textView.setProperties(textProperties) + val textProperties = model.value.convertToElement() + textProperties?.let { holder.textView.setProperties(it) } holder.textView.setOnClickListener { - textProperties.actionProperties?.let { actionProperties -> + textProperties?.actionProperties?.let { actionProperties -> holder.textView.setOnClickListener { onClickListener?.invoke(actionProperties) } diff --git a/android_kmp/craftd-xml/src/androidMain/res/layout/button.xml b/android_kmp/craftd-xml/src/main/res/layout/button.xml similarity index 100% rename from android_kmp/craftd-xml/src/androidMain/res/layout/button.xml rename to android_kmp/craftd-xml/src/main/res/layout/button.xml diff --git a/android_kmp/generate_local_libraries.sh b/android_kmp/generate_local_libraries.sh new file mode 100644 index 0000000..bb175f8 --- /dev/null +++ b/android_kmp/generate_local_libraries.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ============================================================ +# CONFIGURAÇÕES DO SCRIPT +# ============================================================ +VERSION="${VERSION:-1.0.0-local}" +SAMPLE_PATH="${SAMPLE_PATH:-./KMP-Sample/gradle}" +MODULES="${MODULES:-craftd-core craftd-compose}" +TOML_KEY="${TOML_KEY:-craftdCompose}" +TOML_PATH="$SAMPLE_PATH/libs.versions.toml" + +# ============================================================ +# sed compatibilidade (GNU vs BSD/macOS) +# ============================================================ +if command -v gsed >/dev/null 2>&1; then + SED=gsed + SED_INPLACE=(-i) +elif sed --version >/dev/null 2>&1; then + SED=sed + SED_INPLACE=(-i) +else + SED=sed + SED_INPLACE=(-i '') +fi + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$ROOT_DIR" + +echo ">> Using VERSION: $VERSION" +echo ">> SAMPLE_PATH: $SAMPLE_PATH" +echo ">> TOML_PATH: $TOML_PATH" +echo ">> TOML_KEY: $TOML_KEY" + +# ============================================================ +# Atualiza VERSION / VERSION_NAME nos gradle.properties +# ============================================================ +for m in $MODULES; do + props="$m/gradle.properties" + if [ -f "$props" ]; then + echo ">> Updating $props → VERSION=$VERSION" + "$SED" "${SED_INPLACE[@]}" "s/^VERSION=.*/VERSION=${VERSION}/" "$props" || true + "$SED" "${SED_INPLACE[@]}" "s/^VERSION_NAME=.*/VERSION_NAME=${VERSION}/" "$props" || true + else + echo "!! Missing $props (skipping)" + fi +done + +# ============================================================ +# Build release dos mĂłdulos +# ============================================================ +for m in $MODULES; do + echo ">> Assembling release for :$m" + ./gradlew :"$m":assembleRelease +done + +# ============================================================ +# Publish no mavenLocal +# ============================================================ +for m in $MODULES; do + echo ">> Publishing :$m to mavenLocal" + ./gradlew :"$m":publishToMavenLocal +done + +# ============================================================ +# Atualiza a versĂŁo no libs.versions.toml +# ============================================================ +if [ -f "$TOML_PATH" ]; then + echo ">> Updating TOML key $TOML_KEY → \"$VERSION\"" + "$SED" "${SED_INPLACE[@]}" \ + "s/^[[:space:]]*${TOML_KEY}[[:space:]]*=[[:space:]]*\"[^\"]*\"/${TOML_KEY} = \"${VERSION}\"/" \ + "$TOML_PATH" || true +else + echo "!! Error: TOML not found at $TOML_PATH" +fi + +echo ">> DONE: Published version \"$VERSION\" to mavenLocal and updated TOML." diff --git a/android_kmp/gradle/libs.versions.toml b/android_kmp/gradle/libs.versions.toml index 8d5cad1..9207595 100644 --- a/android_kmp/gradle/libs.versions.toml +++ b/android_kmp/gradle/libs.versions.toml @@ -1,42 +1,67 @@ [versions] -kotlin = "1.9.21" -android_gradle_plugin = "8.2.2" -kotlinx-collections-immutable = "0.3.7" -plugin-maven = "0.28.0" +androidx-activity = "1.11.0" +androidx-lifecycle = "2.9.4" -jackson = "2.12.7" +# Core toolchain +kotlin = "2.2.21" +android_gradle_plugin = "8.10.0" +compose_plugin = "1.8.2" -#Test -test_junit = "4.13.2" -androidx_core_testing = "2.2.0" -mockk = "1.13.7" -kotlinx-coroutines-test = "1.5.1" +# AndroidX / Google +androidx_core_ktx = "1.13.1" -#Android -androidx_appcompat = "1.6.1" -material = "1.11.0" +androidx_appcompat = "1.7.0" +material = "1.12.0" +lifecycle = "2.8.4" dynamic_animation = "1.0.0" -viewmodel = "2.7.0" -androidx_core_ktx = "1.13.0" -#Compose -lifecycle_version = "2.7.0" -compose_plugin = "1.6.1" +# KotlinX +kotlinx-collections-immutable = "0.4.0" +kotlinx-serialization = "1.9.0" +kotlinx-coroutines = "1.10.2" + +# Jackson +jackson = "2.17.2" + +# Test +test_junit = "4.13.2" +androidx_core_testing = "2.2.0" +mockk = "1.13.12" +kotlinx-coroutines-test = "1.8.1" + +# Maven Publish plugin +plugin-maven = "0.28.0" [libraries] -kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlinx-collections-immutable" } +androidx-lifecycle-viewmodelCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" } +androidx-lifecycle-runtimeCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } +androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" } plugin_maven = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "plugin-maven" } kotlin_gradle_plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } android_gradle_plugin = { group = "com.android.tools.build", name = "gradle", version.ref = "android_gradle_plugin" } +serialization = { module = "org.jetbrains.kotlin.plugin.serialization:org.jetbrains.kotlin.plugin.serialization.gradle.plugin", version.ref = "kotlin" } # Kotlin -kotlin_stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk7", version.ref = "kotlin" } +kotlin_stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" } kotlin_reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" } +kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } -# Android Support +# AndroidX / Google androidx_core = { group = "androidx.core", name = "core-ktx", version.ref = "androidx_core_ktx" } androidx_appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx_appcompat" } androidx_dynamicanimation = { group = "androidx.dynamicanimation", name = "dynamicanimation", version.ref = "dynamic_animation" } +google_material = { group = "com.google.android.material", name = "material", version.ref = "material" } + +# Lifecycle / Compose interop +compose_lifecycle = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" } + +# KotlinX +kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlinx-collections-immutable" } + +# Jackson +fasterxml_jackson = { group = "com.fasterxml.jackson.core", name = "jackson-core", version.ref = "jackson" } +fasterxml_jackson_databind = { group = "com.fasterxml.jackson.core", name = "jackson-databind", version.ref = "jackson" } # Test junit = { group = "junit", name = "junit", version.ref = "test_junit" } @@ -45,16 +70,6 @@ mockk_android = { group = "io.mockk", name = "mockk-android", version.ref = "moc viewmodel_test = { group = "androidx.arch.core", name = "core-testing", version.ref = "androidx_core_testing" } coroutines_test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinx-coroutines-test" } -# Google -google_material = { group = "com.google.android.material", name = "material", version.ref = "material" } - -# Compose -compose_lifecycle = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle_version" } - -#jackson -fasterxml_jackson = { group = "com.fasterxml.jackson.core", name = "jackson-core", version.ref = "jackson" } -fasterxml_jackson_databind = { group = "com.fasterxml.jackson.core", name = "jackson-databind", version.ref = "jackson" } - [bundles] test = ["junit", "mockk", "mockk_android", "viewmodel_test", "coroutines_test"] androidSupport = ["androidx_core", "androidx_appcompat", "androidx_dynamicanimation", "google_material"] @@ -63,9 +78,11 @@ kotlin = ["androidx_core", "kotlin_stdlib", "kotlin_reflect"] [plugins] android_application = { id = "com.android.application", version.ref = "android_gradle_plugin" } android_library = { id = "com.android.library", version.ref = "android_gradle_plugin" } - kotlin_android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin_kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } kotlin_parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } +plugin_maven = { id = "com.vanniktech.maven.publish", version.ref = "plugin-maven" } kotlin_multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } -jetbrains_compose = { id = "org.jetbrains.compose", version.ref = "compose_plugin" } \ No newline at end of file +jetbrains_compose = { id = "org.jetbrains.compose", version.ref = "compose_plugin" } +kotlin_compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } diff --git a/android_kmp/gradle/wrapper/gradle-wrapper.properties b/android_kmp/gradle/wrapper/gradle-wrapper.properties index 1af9e09..cc58ebc 100644 --- a/android_kmp/gradle/wrapper/gradle-wrapper.properties +++ b/android_kmp/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ +#Wed Nov 12 09:25:51 BRT 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/android_kmp/iosApp/Configuration/Config.xcconfig b/android_kmp/iosApp/Configuration/Config.xcconfig new file mode 100644 index 0000000..ebded75 --- /dev/null +++ b/android_kmp/iosApp/Configuration/Config.xcconfig @@ -0,0 +1,7 @@ +TEAM_ID= + +PRODUCT_NAME=AppSampleCMP +PRODUCT_BUNDLE_IDENTIFIER=org.example.project.AppSampleCMP + +CURRENT_PROJECT_VERSION=1 +MARKETING_VERSION=1.0 diff --git a/android_kmp/iosApp/iosApp.xcodeproj/project.pbxproj b/android_kmp/iosApp/iosApp.xcodeproj/project.pbxproj new file mode 100644 index 0000000..2e962ce --- /dev/null +++ b/android_kmp/iosApp/iosApp.xcodeproj/project.pbxproj @@ -0,0 +1,375 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXFileReference section */ + 1C6D5D6AEED764F150B58234 /* AppSampleCMP.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppSampleCMP.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + DD4F3A6E0BEF16C61F9E520E /* Exceptions for "iosApp" folder in "iosApp" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = 8A7966F07A76D1CD44D5D9A0 /* iosApp */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 186F065D2790AB03C5519CDB /* Configuration */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = Configuration; + sourceTree = ""; + }; + 460BCC607CED76E03E66BCB1 /* iosApp */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + DD4F3A6E0BEF16C61F9E520E /* Exceptions for "iosApp" folder in "iosApp" target */, + ); + path = iosApp; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 98C663315D8315764846D464 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 47B33B1E94C517C9648A17F8 = { + isa = PBXGroup; + children = ( + 186F065D2790AB03C5519CDB /* Configuration */, + 460BCC607CED76E03E66BCB1 /* iosApp */, + 8EDB1AF49670CF89697EE5CC /* Products */, + ); + sourceTree = ""; + }; + 8EDB1AF49670CF89697EE5CC /* Products */ = { + isa = PBXGroup; + children = ( + 1C6D5D6AEED764F150B58234 /* AppSampleCMP.app */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8A7966F07A76D1CD44D5D9A0 /* iosApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = B3DA73551DFE5C760F6BAE0C /* Build configuration list for PBXNativeTarget "iosApp" */; + buildPhases = ( + DBB26F6D35B891A8C039AA55 /* Compile Kotlin Framework */, + 94266FB9F877C4D28E1523B9 /* Sources */, + 98C663315D8315764846D464 /* Frameworks */, + 4EE63F0558EB3D826FF64E52 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 460BCC607CED76E03E66BCB1 /* iosApp */, + ); + name = iosApp; + packageProductDependencies = ( + ); + productName = iosApp; + productReference = 1C6D5D6AEED764F150B58234 /* AppSampleCMP.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D485713DA410197906CD867F /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1620; + LastUpgradeCheck = 1620; + TargetAttributes = { + 8A7966F07A76D1CD44D5D9A0 = { + CreatedOnToolsVersion = 16.2; + }; + }; + }; + buildConfigurationList = E7CA328A9B093AD22CA3FF50 /* Build configuration list for PBXProject "iosApp" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 47B33B1E94C517C9648A17F8; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = 8EDB1AF49670CF89697EE5CC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8A7966F07A76D1CD44D5D9A0 /* iosApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4EE63F0558EB3D826FF64E52 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + DBB26F6D35B891A8C039AA55 /* Compile Kotlin Framework */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Compile Kotlin Framework"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cd \"$SRCROOT/..\"\n./gradlew :app-sample-cmp:embedAndSignAppleFrameworkForXcode\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 94266FB9F877C4D28E1523B9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 36637EB77600F59FAC279BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = arm64; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; + DEVELOPMENT_TEAM = P8ZZXHC5BB; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = iosApp/Info.plist; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 17.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 4B2DA88F7255D3CC1C0053B8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = 186F065D2790AB03C5519CDB /* Configuration */; + baseConfigurationReferenceRelativePath = Config.xcconfig; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.2; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 57024DBAD30D247B7DC32964 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = arm64; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; + DEVELOPMENT_TEAM = "${TEAM_ID}"; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = iosApp/Info.plist; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 17.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + D22FFC51FE50EC82F2E5EC06 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = 186F065D2790AB03C5519CDB /* Configuration */; + baseConfigurationReferenceRelativePath = Config.xcconfig; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.2; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B3DA73551DFE5C760F6BAE0C /* Build configuration list for PBXNativeTarget "iosApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 36637EB77600F59FAC279BE5 /* Debug */, + 57024DBAD30D247B7DC32964 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E7CA328A9B093AD22CA3FF50 /* Build configuration list for PBXProject "iosApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D22FFC51FE50EC82F2E5EC06 /* Debug */, + 4B2DA88F7255D3CC1C0053B8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D485713DA410197906CD867F /* Project object */; +} diff --git a/android_kmp/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json b/android_kmp/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/android_kmp/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/android_kmp/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/android_kmp/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..4e8d485 --- /dev/null +++ b/android_kmp/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,36 @@ +{ + "images" : [ + { + "filename" : "app-icon-1024.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/android_kmp/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png b/android_kmp/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png new file mode 100644 index 0000000..53fc536 Binary files /dev/null and b/android_kmp/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png differ diff --git a/android_kmp/iosApp/iosApp/Assets.xcassets/Contents.json b/android_kmp/iosApp/iosApp/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/android_kmp/iosApp/iosApp/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/android_kmp/iosApp/iosApp/ContentView.swift b/android_kmp/iosApp/iosApp/ContentView.swift new file mode 100644 index 0000000..c765ff2 --- /dev/null +++ b/android_kmp/iosApp/iosApp/ContentView.swift @@ -0,0 +1,21 @@ +import UIKit +import SwiftUI +import ComposeApp + +struct ComposeView: UIViewControllerRepresentable { + func makeUIViewController(context: Context) -> UIViewController { + MainViewControllerKt.MainViewController() + } + + func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} +} + +struct ContentView: View { + var body: some View { + ComposeView() + .ignoresSafeArea() + } +} + + + diff --git a/android_kmp/iosApp/iosApp/Info.plist b/android_kmp/iosApp/iosApp/Info.plist new file mode 100644 index 0000000..11845e1 --- /dev/null +++ b/android_kmp/iosApp/iosApp/Info.plist @@ -0,0 +1,8 @@ + + + + + CADisableMinimumFrameDurationOnPhone + + + diff --git a/android_kmp/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json b/android_kmp/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/android_kmp/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/android_kmp/iosApp/iosApp/iOSApp.swift b/android_kmp/iosApp/iosApp/iOSApp.swift new file mode 100644 index 0000000..d83dca6 --- /dev/null +++ b/android_kmp/iosApp/iosApp/iOSApp.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct iOSApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} \ No newline at end of file diff --git a/android_kmp/settings.gradle.kts b/android_kmp/settings.gradle.kts index 21499b6..2f6eaac 100644 --- a/android_kmp/settings.gradle.kts +++ b/android_kmp/settings.gradle.kts @@ -1,10 +1,12 @@ @file:Suppress("UnstableApiUsage") + pluginManagement { includeBuild("build-logic") repositories { gradlePluginPortal() google() mavenCentral() + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } } @@ -13,13 +15,15 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } - } + rootProject.name = "CraftD" -include(":app-sample") + +include(":app-sample-android", ":app-sample-cmp") include(":craftd-core") include(":craftd-xml") include(":craftd-compose") -enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") \ No newline at end of file +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") diff --git a/docs/how-to-use/compose.md b/docs/how-to-use/compose.md index ecaec7d..84233cc 100644 --- a/docs/how-to-use/compose.md +++ b/docs/how-to-use/compose.md @@ -1,29 +1,50 @@ -# Jetpack Compose +# Jetpack Compose / CMP -- Create your ComponentPropertyClass with properties that you need. In this example, I used checkbox component: +- Create your `ComponentPropertyClass` with all the properties your component needs. + In this example, we’re using a **checkbox component**. !!! warning "Immutable and Stable annotations" - Here we have some points to consider To avoid unnecessary recompositions at your component. We recommend use the `@Immutable` and `@Stable` annotations in your properties. +To avoid unnecessary recompositions in your component, +we recommend using the `@Immutable` and `@Stable` annotations in your properties. + +--- + +### 1. Enable Kotlin Serialization +In your **root build.gradle.kts**, add the Kotlin serialization plugin (version **2.2.21** or higher): + +```gradle +id("org.jetbrains.kotlin.plugin.serialization") version "2.2.21" +``` + +In your **module build.gradle.kts** add + +```gradle + implementation(libs.kotlinx.serialization.json) +``` + +2. Create your owner object that has the same field in your json like: (This class must match the structure of the JSON that will be parsed:) ```kotlin -@JsonIgnoreProperties(ignoreUnknown = true) -@Immutable @Stable +@Immutable +@Serializable data class CheckBoxProperties( - @JsonProperty("text") val text: String? = null, + @SerialName("text") val text: String? = null, ... define your properties here ) ``` -- Add your Component json object in `Dymanic.json`: +!!! tip "Note" + + You can use your component object in dynamic.json inside the sample project [app-sample-android](https://github.com/CodandoTV/CraftD/tree/issue-59/convert-to-kmp/android_kmp/app-sample-android) or [KMP-sample](https://github.com/CodandoTV/CraftD/tree/issue-59/convert-to-kmp/android_kmp/KMP-Sample): ```json { - "key": "CraftDCheckBox", - "value": { - ... define your properties here - } - } + "key": "CraftDCheckBox", + "value": { + ... define your properties here + } +} ``` - Create your Component @@ -53,7 +74,7 @@ class CraftDCheckBoxBuilder( !!! tip "Note" - This Builder must extend CraftBuilder Class and override craft method. +This Builder must extend CraftBuilder Class and override craft method. ```kotlin class CraftDCheckBoxBuilder( @@ -80,7 +101,7 @@ fun InitialScreen( val properties by vm.properties.collectAsStateWithLifecycle() val dynamicBuilder = remember { CraftDBuilderManager().add( - CraftDCheckBoxBuilder() + CraftDCheckBoxBuilder() ) } LaunchedEffect(Unit) { diff --git a/docs/index.md b/docs/index.md index fff5d75..c5adf87 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,66 +4,28 @@ ### 🔗 Compatibility -| Tech | Support | -|----------------------------|------------------| -| View System - Android | ✅ Supported | -| Jetpack Compose - Android | ✅ Supported | -| Widgets Flutter | ✅ Supported | -| SwiftUI - iOS | ✅ Supported | -| Compose Multiplatform | ⚒ In Progress | +| Tech | Support | +|----------------------------|-----------------| +| View System - Android | ✅ Supported | +| Jetpack Compose - Android | ✅ Supported | +| Widgets Flutter | ✅ Supported | +| SwiftUI - iOS | ✅ Supported | +| Compose Multiplatform | ✅ Supported | ### Components that already exist in the library -| Component | Android Compose | Android View | Flutter | SwiftUI | -|-------------------|-----------------|--------------|---------|---------| -| Button | X | X | X | - | -| Text | X | X | X | X | -| Checkbox | X | - | - | - | - -### How to create a custom component? - -- Create a data structure to represent your component: - -```kotlin -@JsonIgnoreProperties(ignoreUnknown = true) -@Immutable -@Stable -data class CheckBoxProperties( - @JsonProperty("text") val text: String? = null, - ... rest of your properties -) -``` - -- Add your Component json object in _Dymanic.json_ - -```json -{ - "key": "CraftDCheckBox", - "value": { - ... rest of your properties - } -} -``` - -- Create your component: - -```kotlin -@Composable -fun CraftDCheckBox( - checkboxProperties: CheckBoxProperties, - modifier: Modifier = Modifier, - onChecked: (Boolean) -> Unit -) { - ... Rest of your code -} -``` +| Component | Jetpack Compose / CMP | Android View | Flutter | SwiftUI | +|-------------------|-----------------------|--------------|---------|---------| +| Button | X | X | X | - | +| Text | X | X | X | X | +| Checkbox | X | - | - | - | ### Screen recordings
![Compose Android](./assets/video/compose-android.gif){ width="300" } -
Compose Android
+
JetPack Compose / CMP
@@ -86,5 +48,4 @@ fun CraftDCheckBox( !!! info "Credits" A Server Driven UI library for Android. - Inspired by the [_DynamicView_](https://github.com/rviannaoliveira/DynamicView). - + Inspired by the [_DynamicView_](https://github.com/rviannaoliveira/DynamicView). \ No newline at end of file diff --git a/docs/setup.md b/docs/setup.md index 4440c4a..d3694ec 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -1,6 +1,6 @@ # Setup -## Android +## Android / CMP - Add in your settings.gradle mavenCetral: @@ -29,7 +29,7 @@ dependencyResolutionManagement { ``` !!! example "Core" - Core - Is meant to be used for you to customize even the craftD mechanism +Core - Is meant to be used for you to customize even the craftD mechanism ```kotlin implementation("io.github.codandotv:craftd-core:${last_version}") @@ -40,7 +40,7 @@ dependencyResolutionManagement { - Add your pod ‘CraftDSwiftUI’ !!! warning "In Progress" - This section is in progress... +This section is in progress... ## Flutter @@ -53,7 +53,7 @@ flutter pub add craftd_widget This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get): !!! example "pubspec.yml" - ```yaml - dependencies: - craftd_widget: $last_version - ``` \ No newline at end of file +```yaml +dependencies: + craftd_widget: $last_version +``` \ No newline at end of file diff --git a/flutter/sample/macos/Runner.xcodeproj/project.pbxproj b/flutter/sample/macos/Runner.xcodeproj/project.pbxproj index 68911e3..83b5e35 100644 --- a/flutter/sample/macos/Runner.xcodeproj/project.pbxproj +++ b/flutter/sample/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -182,7 +182,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { @@ -235,6 +235,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -344,7 +345,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -423,7 +424,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -470,7 +471,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/flutter/sample/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter/sample/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index ca98626..ebe148b 100644 --- a/flutter/sample/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/flutter/sample/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ diff --git a/flutter/sample/macos/Runner/AppDelegate.swift b/flutter/sample/macos/Runner/AppDelegate.swift index d53ef64..b3c1761 100644 --- a/flutter/sample/macos/Runner/AppDelegate.swift +++ b/flutter/sample/macos/Runner/AppDelegate.swift @@ -1,9 +1,13 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } diff --git a/flutter/sample/pubspec.lock b/flutter/sample/pubspec.lock index 5fde049..c19e02b 100644 --- a/flutter/sample/pubspec.lock +++ b/flutter/sample/pubspec.lock @@ -159,7 +159,7 @@ packages: path: "../craftd_widget" relative: true source: path - version: "1.0.0" + version: "1.0.2" crypto: dependency: transitive description: @@ -318,26 +318,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -547,10 +547,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" timing: dependency: transitive description: @@ -571,10 +571,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -608,5 +608,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.7.0-0 <4.0.0" + dart: ">=3.8.0-0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/ios/craftd-swiftui/.idea/misc.xml b/ios/craftd-swiftui/.idea/misc.xml new file mode 100644 index 0000000..5e24607 --- /dev/null +++ b/ios/craftd-swiftui/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/ios/craftd-swiftui/.idea/modules.xml b/ios/craftd-swiftui/.idea/modules.xml new file mode 100644 index 0000000..382f050 --- /dev/null +++ b/ios/craftd-swiftui/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file