diff --git a/.gitignore b/.gitignore index 124fa051..2be2e72f 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,5 @@ yarn.lock # Mac .DS_Store + +.kotlin diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 6789e2c1..00000000 --- a/app/build.gradle +++ /dev/null @@ -1,120 +0,0 @@ -plugins { - id 'com.android.application' - id 'kotlin-android' - alias(libs.plugins.dependency.guard) -} - -android { - compileSdk = Integer.parseInt(libs.versions.android.compile.sdk.get()) - - namespace = "com.handstandsam.shoppingapp" - - defaultConfig { - applicationId "com.handstandsam.shoppingapp" - minSdkVersion Integer.parseInt(libs.versions.android.min.sdk.get()) - targetSdkVersion Integer.parseInt(libs.versions.android.target.sdk.get()) - versionCode 1 - versionName "1.0" - vectorDrawables.useSupportLibrary = true - testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' - } - - testOptions { - execution 'ANDROIDX_TEST_ORCHESTRATOR' - animationsDisabled = true - } - - variantFilter { variant -> - setIgnore(!variant.name.toLowerCase().endsWith("debug")) - } - - lint { - baseline = file("lint-baseline.xml") - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - buildFeatures { - compose true - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 - } - - composeOptions { - kotlinCompilerExtensionVersion libs.versions.compose.compiler.get() - } -} - -dependencies { - implementation project(":compose-ui") - - implementation project(":models") - implementation project(":mock-data") - implementation project(":shopping-cart") - - // AndroidX Libraries - implementation libs.androidx.appcompat.v7 - implementation libs.androidx.material - implementation libs.androidx.lifecycle.runtime.ktx - - // Networking - implementation libs.glide - implementation libs.okhttp - implementation project(":networking") - debugImplementation libs.okhttp.logging.interceptor - - // Kotlin - implementation libs.kotlin.coroutines - implementation libs.kotlin.coroutines.android - - //Flavor Modules - implementation project(":app-flavor-inmemory") -// implementation project(":app-flavor-mockserver") -// implementation project(":app-flavor-liveserver") - - //Logging - implementation libs.timber - - // Compose - implementation libs.androidx.compose.compiler - implementation libs.androidx.compose.runtime - implementation libs.androidx.compose.ui - implementation libs.androidx.compose.foundation - implementation libs.androidx.compose.material - implementation libs.androidx.compose.material.icons.extended - implementation libs.androidx.compose.animation - implementation libs.androidx.compose.ui.tooling - implementation libs.androidx.activity.compose - - implementation libs.accompanist.coil - implementation libs.coil.compose - implementation libs.landscapist.coil - implementation libs.androidx.lifecycle.runtime.ktx - - //JVM Tests Only - testImplementation libs.junit - - androidTestImplementation libs.androidx.espresso - androidTestImplementation libs.androidx.espresso.contrib - androidTestImplementation libs.androidx.test.rules - androidTestImplementation libs.androidx.testrunner - androidTestImplementation(project(":app-test-suite")) -} - -dependencyGuard { - configuration("debugRuntimeClasspath") { - modules = true - } -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 00000000..0b6f49ba --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,113 @@ +plugins { + id("com.android.application") + id("kotlin-android") + alias(libs.plugins.dependency.guard) + alias(libs.plugins.compose.compiler) +} + +android { + compileSdk = Integer.parseInt(libs.versions.android.compile.sdk.get()) + + namespace = "com.handstandsam.shoppingapp" + + defaultConfig { + applicationId = "com.handstandsam.shoppingapp" + minSdk = Integer.parseInt(libs.versions.android.min.sdk.get()) + targetSdk = Integer.parseInt(libs.versions.android.target.sdk.get()) + versionCode = 1 + versionName = "1.0" + vectorDrawables.useSupportLibrary = true + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + testOptions { + execution = "ANDROIDX_TEST_ORCHESTRATOR" + animationsDisabled = true + } + + androidComponents { + beforeVariants { variantBuilder -> + if (variantBuilder.buildType != "debug") { + variantBuilder.enable = false + } + } + } + + lint { + baseline = file("lint-baseline.xml") + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + buildFeatures { + compose = true + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8.toString() + } +} + +dependencies { + implementation(project(":compose-ui")) + + implementation(project(":models")) + implementation(project(":mock-data")) + implementation(project(":shopping-cart")) + + // AndroidX Libraries + implementation(libs.androidx.appcompat.v7) + implementation(libs.androidx.material) + implementation(libs.androidx.lifecycle.runtime.ktx) + + // Networking) + implementation(libs.glide) + implementation(libs.okhttp) + implementation(project(":networking")) + debugImplementation(libs.okhttp.logging.interceptor) + + // Kotlin) + implementation(libs.kotlin.coroutines) + implementation(libs.kotlin.coroutines.android) + + //Flavor Modules) + implementation(project(":app-flavor-inmemory")) +// implementation( project(":app-flavor-mockserver")) +// implementation( project(":app-flavor-liveserver")) + + //Logging + implementation(libs.timber) + + // Compose +// implementation( libs.androidx.compose.compiler) + implementation(libs.androidx.compose.runtime) + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.foundation) + implementation(libs.androidx.compose.material) + implementation(libs.androidx.compose.material.icons.extended) + implementation(libs.androidx.compose.animation) + implementation(libs.androidx.compose.ui.tooling) + implementation(libs.androidx.activity.compose) + implementation(libs.accompanist.coil) + implementation(libs.coil.compose) + implementation(libs.landscapist.coil) + implementation(libs.androidx.lifecycle.runtime.ktx) + + //JVM Tests Only + testImplementation(libs.junit) + + androidTestImplementation(libs.androidx.espresso) + androidTestImplementation(libs.androidx.espresso.contrib) + androidTestImplementation(libs.androidx.test.rules) + androidTestImplementation(libs.androidx.testrunner) + androidTestImplementation(project(":app-test-suite")) +} + +dependencyGuard { + configuration("debugRuntimeClasspath") { + modules = true + } +} diff --git a/app/dependencies/debugRuntimeClasspath.txt b/app/dependencies/debugRuntimeClasspath.txt index c4f23331..30c1a899 100644 --- a/app/dependencies/debugRuntimeClasspath.txt +++ b/app/dependencies/debugRuntimeClasspath.txt @@ -8,68 +8,69 @@ androidx.activity:activity-compose:1.7.2 androidx.activity:activity-ktx:1.7.2 androidx.activity:activity:1.7.2 androidx.annotation:annotation-experimental:1.3.0 -androidx.annotation:annotation-jvm:1.6.0 -androidx.annotation:annotation:1.6.0 +androidx.annotation:annotation-jvm:1.7.0 +androidx.annotation:annotation:1.7.0 androidx.appcompat:appcompat-resources:1.6.1 androidx.appcompat:appcompat:1.6.1 androidx.arch.core:core-common:2.2.0 androidx.arch.core:core-runtime:2.2.0 androidx.autofill:autofill:1.0.0 androidx.cardview:cardview:1.0.0 -androidx.collection:collection:1.2.0 -androidx.compose.animation:animation-android:1.5.1 -androidx.compose.animation:animation-core-android:1.5.1 -androidx.compose.animation:animation-core:1.5.1 -androidx.compose.animation:animation:1.5.1 -androidx.compose.compiler:compiler:1.5.3 -androidx.compose.foundation:foundation-android:1.5.1 -androidx.compose.foundation:foundation-layout-android:1.5.1 -androidx.compose.foundation:foundation-layout:1.5.1 -androidx.compose.foundation:foundation:1.5.1 -androidx.compose.material:material-android:1.5.1 -androidx.compose.material:material-icons-core-android:1.5.1 -androidx.compose.material:material-icons-core:1.5.1 -androidx.compose.material:material-icons-extended-android:1.5.1 -androidx.compose.material:material-icons-extended:1.5.1 -androidx.compose.material:material-ripple-android:1.5.1 -androidx.compose.material:material-ripple:1.5.1 -androidx.compose.material:material:1.5.1 -androidx.compose.runtime:runtime-android:1.5.1 -androidx.compose.runtime:runtime-saveable-android:1.5.1 -androidx.compose.runtime:runtime-saveable:1.5.1 -androidx.compose.runtime:runtime:1.5.1 -androidx.compose.ui:ui-android:1.5.1 -androidx.compose.ui:ui-geometry-android:1.5.1 -androidx.compose.ui:ui-geometry:1.5.1 -androidx.compose.ui:ui-graphics-android:1.5.1 -androidx.compose.ui:ui-graphics:1.5.1 -androidx.compose.ui:ui-text-android:1.5.1 -androidx.compose.ui:ui-text:1.5.1 -androidx.compose.ui:ui-tooling-android:1.5.1 -androidx.compose.ui:ui-tooling-data-android:1.5.1 -androidx.compose.ui:ui-tooling-data:1.5.1 -androidx.compose.ui:ui-tooling-preview-android:1.5.1 -androidx.compose.ui:ui-tooling-preview:1.5.1 -androidx.compose.ui:ui-tooling:1.5.1 -androidx.compose.ui:ui-unit-android:1.5.1 -androidx.compose.ui:ui-unit:1.5.1 -androidx.compose.ui:ui-util-android:1.5.1 -androidx.compose.ui:ui-util:1.5.1 -androidx.compose.ui:ui:1.5.1 +androidx.collection:collection-jvm:1.4.0 +androidx.collection:collection-ktx:1.4.0 +androidx.collection:collection:1.4.0 +androidx.compose.animation:animation-android:1.6.8 +androidx.compose.animation:animation-core-android:1.6.8 +androidx.compose.animation:animation-core:1.6.8 +androidx.compose.animation:animation:1.6.8 +androidx.compose.foundation:foundation-android:1.6.8 +androidx.compose.foundation:foundation-layout-android:1.6.8 +androidx.compose.foundation:foundation-layout:1.6.8 +androidx.compose.foundation:foundation:1.6.8 +androidx.compose.material:material-android:1.6.8 +androidx.compose.material:material-icons-core-android:1.6.8 +androidx.compose.material:material-icons-core:1.6.8 +androidx.compose.material:material-icons-extended-android:1.6.8 +androidx.compose.material:material-icons-extended:1.6.8 +androidx.compose.material:material-ripple-android:1.6.8 +androidx.compose.material:material-ripple:1.6.8 +androidx.compose.material:material:1.6.8 +androidx.compose.runtime:runtime-android:1.6.8 +androidx.compose.runtime:runtime-saveable-android:1.6.8 +androidx.compose.runtime:runtime-saveable:1.6.8 +androidx.compose.runtime:runtime:1.6.8 +androidx.compose.ui:ui-android:1.6.8 +androidx.compose.ui:ui-geometry-android:1.6.8 +androidx.compose.ui:ui-geometry:1.6.8 +androidx.compose.ui:ui-graphics-android:1.6.8 +androidx.compose.ui:ui-graphics:1.6.8 +androidx.compose.ui:ui-text-android:1.6.8 +androidx.compose.ui:ui-text:1.6.8 +androidx.compose.ui:ui-tooling-android:1.6.8 +androidx.compose.ui:ui-tooling-data-android:1.6.8 +androidx.compose.ui:ui-tooling-data:1.6.8 +androidx.compose.ui:ui-tooling-preview-android:1.6.8 +androidx.compose.ui:ui-tooling-preview:1.6.8 +androidx.compose.ui:ui-tooling:1.6.8 +androidx.compose.ui:ui-unit-android:1.6.8 +androidx.compose.ui:ui-unit:1.6.8 +androidx.compose.ui:ui-util-android:1.6.8 +androidx.compose.ui:ui-util:1.6.8 +androidx.compose.ui:ui:1.6.8 androidx.concurrent:concurrent-futures:1.1.0 androidx.constraintlayout:constraintlayout-solver:2.0.1 androidx.constraintlayout:constraintlayout:2.0.1 androidx.coordinatorlayout:coordinatorlayout:1.1.0 -androidx.core:core-ktx:1.10.0 -androidx.core:core:1.10.0 +androidx.core:core-ktx:1.12.0 +androidx.core:core:1.12.0 androidx.cursoradapter:cursoradapter:1.0.0 androidx.customview:customview-poolingcontainer:1.0.0 androidx.customview:customview:1.1.0 androidx.documentfile:documentfile:1.0.0 androidx.drawerlayout:drawerlayout:1.1.1 androidx.dynamicanimation:dynamicanimation:1.0.0 -androidx.emoji2:emoji2-views-helper:1.4.0 -androidx.emoji2:emoji2:1.4.0 +androidx.emoji2:emoji2-views-helper:1.3.0 +androidx.emoji2:emoji2:1.3.0 androidx.exifinterface:exifinterface:1.3.3 androidx.fragment:fragment:1.3.6 androidx.interpolator:interpolator:1.0.0 @@ -144,24 +145,22 @@ io.ktor:ktor-websocket-serialization-jvm:2.1.0 io.ktor:ktor-websocket-serialization:2.1.0 io.ktor:ktor-websockets-jvm:2.1.0 io.ktor:ktor-websockets:2.1.0 -org.jetbrains.compose.foundation:foundation:1.5.1 -org.jetbrains.compose.material:material:1.5.1 -org.jetbrains.compose.ui:ui:1.5.1 org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.7.10 org.jetbrains.kotlin:kotlin-parcelize-runtime:1.7.10 -org.jetbrains.kotlin:kotlin-stdlib-common:1.9.10 -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10 -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10 -org.jetbrains.kotlin:kotlin-stdlib:1.9.10 -org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 -org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3 -org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3 -org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.7.3 -org.jetbrains.kotlinx:kotlinx-coroutines-slf4j:1.7.3 -org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.4.1 -org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.1 -org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.4.1 -org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1 +org.jetbrains.kotlin:kotlin-stdlib-common:2.0.0 +org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0 +org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0 +org.jetbrains.kotlin:kotlin-stdlib:2.0.0 +org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1 +org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.1 +org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.1 +org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 +org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.8.1 +org.jetbrains.kotlinx:kotlinx-coroutines-slf4j:1.8.1 +org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.1 +org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.1 +org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.1 +org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.1 +org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1 org.jetbrains:annotations:23.0.0 org.slf4j:slf4j-api:1.7.36 diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 4fc93a9e..8246c9b4 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -2,7 +2,7 @@ # By default, the flags in this file are appended to flags specified # in /Users/handstandtech/dev/android-sdk-mac_x86/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. +# directive in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/build.gradle b/build.gradle.kts similarity index 57% rename from build.gradle rename to build.gradle.kts index 8b7ba74a..83eca529 100644 --- a/build.gradle +++ b/build.gradle.kts @@ -4,16 +4,20 @@ buildscript { mavenCentral() google() gradlePluginPortal() - maven { url = "https://maven.pkg.jetbrains.space/public/p/compose/dev" } - maven { url = "https://s01.oss.sonatype.org/content/repositories/snapshots/" } +// maven { url = "https://maven.pkg.jetbrains.space/public/p/compose/dev" } +// maven { url = "https://s01.oss.sonatype.org/content/repositories/snapshots/" } } dependencies { classpath(libs.android.gradle.plugin) - classpath(libs.kotlin.gradle.plugin) +// classpath(libs.kotlin.gradle.plugin) classpath(libs.sqldelight.gradle.plugin) + classpath(libs.kotlin.gradle.plugin) classpath("com.handstandsam:convention-plugins") - classpath("com.handstandsam.kmp4free:kmp4free:0.1.0") - classpath(libs.jetbrains.compose.gradle.plugin) +// classpath(libs.plugins.compose.compiler) +// classpath("com.handstandsam.kmp4free:kmp4free:0.1.0") +// classpath(libs.jetbrains.compose) +// classpath(libs.plugins.jetbrains.compose) apply false +// classpath(libs.plugins.compose.compiler) apply false // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle.kts files @@ -22,6 +26,8 @@ buildscript { plugins { alias(libs.plugins.dependency.guard) + alias(libs.plugins.kotlin.multiplatform) apply false + alias(libs.plugins.compose.compiler) apply false } dependencyGuard { @@ -34,7 +40,7 @@ allprojects { repositories { google() mavenCentral() - maven { url = "https://maven.pkg.jetbrains.space/public/p/compose/dev" } +// maven { url = "https://maven.pkg.jetbrains.space/public/p/compose/dev" } } } diff --git a/compose-ui/build.gradle.kts b/compose-ui/build.gradle.kts index f7246d94..c2402000 100644 --- a/compose-ui/build.gradle.kts +++ b/compose-ui/build.gradle.kts @@ -1,8 +1,8 @@ -import org.jetbrains.compose.compose +//import org.jetbrains.compose.compose plugins { - kotlin("multiplatform") // kotlin("jvm") doesn't work well in IDEA/AndroidStudio (https://github.com/JetBrains/compose-jb/issues/22) - id("org.jetbrains.compose") + alias(libs.plugins.kotlin.multiplatform) // kotlin("jvm") doesn't work well in IDEA/AndroidStudio (https://github.com/JetBrains/compose-jb/issues/22) + alias(libs.plugins.compose.compiler) } kotlin { @@ -11,9 +11,9 @@ kotlin { } val jvmMain by sourceSets.getting { dependencies { - implementation(compose.ui) - implementation(compose.foundation) - implementation(compose.material) + implementation(libs.androidx.compose.material) + implementation(libs.androidx.compose.foundation) + implementation(libs.androidx.compose.ui) implementation(project(":models")) implementation(project(":mock-data")) diff --git a/dependencies/classpath.txt b/dependencies/classpath.txt index ba19c205..11c49fd1 100644 --- a/dependencies/classpath.txt +++ b/dependencies/classpath.txt @@ -112,36 +112,32 @@ org.codehaus.mojo:animal-sniffer-annotations:1.19 org.glassfish.jaxb:jaxb-runtime:2.3.2 org.glassfish.jaxb:txw2:2.3.2 org.jdom:jdom2:2.0.6 -org.jetbrains.compose:compose-gradle-plugin:1.5.1 org.jetbrains.intellij.deps:trove4j:1.0.20200330 -org.jetbrains.kotlin:kotlin-android-extensions:1.9.10 -org.jetbrains.kotlin:kotlin-build-tools-api:1.9.10 -org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.10 -org.jetbrains.kotlin:kotlin-compiler-runner:1.9.10 -org.jetbrains.kotlin:kotlin-daemon-client:1.9.10 -org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.10 -org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:1.9.10 -org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.10 -org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.9.10 -org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.9.10 -org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.9.10 -org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10 -org.jetbrains.kotlin:kotlin-gradle-plugins-bom:1.9.10 -org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.9.10 -org.jetbrains.kotlin:kotlin-native-utils:1.9.10 -org.jetbrains.kotlin:kotlin-project-model:1.9.10 -org.jetbrains.kotlin:kotlin-reflect:1.8.20-RC2 -org.jetbrains.kotlin:kotlin-scripting-common:1.9.10 -org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.10 -org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.10 -org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.10 -org.jetbrains.kotlin:kotlin-stdlib-common:1.8.20-RC2 +org.jetbrains.kotlin.multiplatform:org.jetbrains.kotlin.multiplatform.gradle.plugin:2.0.0 +org.jetbrains.kotlin.plugin.compose:org.jetbrains.kotlin.plugin.compose.gradle.plugin:2.0.0 +org.jetbrains.kotlin:compose-compiler-gradle-plugin:2.0.0 +org.jetbrains.kotlin:kotlin-build-statistics:2.0.0 +org.jetbrains.kotlin:kotlin-build-tools-api:2.0.0 +org.jetbrains.kotlin:kotlin-compiler-embeddable:2.0.0 +org.jetbrains.kotlin:kotlin-compiler-runner:2.0.0 +org.jetbrains.kotlin:kotlin-daemon-client:2.0.0 +org.jetbrains.kotlin:kotlin-daemon-embeddable:2.0.0 +org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:2.0.0 +org.jetbrains.kotlin:kotlin-gradle-plugin-api:2.0.0 +org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:2.0.0 +org.jetbrains.kotlin:kotlin-gradle-plugin-idea:2.0.0 +org.jetbrains.kotlin:kotlin-gradle-plugin-model:2.0.0 +org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.0 +org.jetbrains.kotlin:kotlin-gradle-plugins-bom:2.0.0 +org.jetbrains.kotlin:kotlin-klib-commonizer-api:2.0.0 +org.jetbrains.kotlin:kotlin-native-utils:2.0.0 +org.jetbrains.kotlin:kotlin-reflect:1.9.22 org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.20-RC2 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20-RC2 -org.jetbrains.kotlin:kotlin-stdlib:1.8.20-RC2 -org.jetbrains.kotlin:kotlin-tooling-core:1.9.10 -org.jetbrains.kotlin:kotlin-util-io:1.9.10 -org.jetbrains.kotlin:kotlin-util-klib:1.9.10 +org.jetbrains.kotlin:kotlin-stdlib:1.9.22 +org.jetbrains.kotlin:kotlin-tooling-core:2.0.0 +org.jetbrains.kotlin:kotlin-util-io:2.0.0 +org.jetbrains.kotlin:kotlin-util-klib:2.0.0 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0 org.jetbrains:annotations:13.0 org.jvnet.staxex:stax-ex:1.8.1 diff --git a/desktop/build.gradle.kts b/desktop/build.gradle.kts index 90c9cb58..1433956e 100644 --- a/desktop/build.gradle.kts +++ b/desktop/build.gradle.kts @@ -1,37 +1,33 @@ -import org.jetbrains.compose.compose import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { - kotlin("multiplatform") // kotlin("jvm") doesn't work well in IDEA/AndroidStudio (https://github.com/JetBrains/compose-jb/issues/22) - id("org.jetbrains.compose") +// alias(libs.plugins.kotlin.multiplatform) + kotlin("jvm") + alias(libs.plugins.compose.compiler) + alias(libs.plugins.jetbrains.compose) + application } -kotlin { - jvm { - withJava() - } - sourceSets { - named("jvmMain") { - dependencies { - implementation(compose.desktop.currentOs) - implementation(project(":compose-ui")) - implementation(project(":mock-data")) - implementation(project(":models")) - implementation(project(":networking")) - implementation(project(":shopping-cart")) - } - } - } +dependencies { + implementation(compose.desktop.currentOs) + implementation(project(":compose-ui")) + implementation(project(":mock-data")) + implementation(project(":models")) + implementation(project(":networking")) + implementation(project(":shopping-cart")) } -compose.desktop { - application { - mainClass = "com.handstandsam.shoppingapp.compose.MainKt" - nativeDistributions { - targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) - packageName = "ShoppingApp Desktop" - packageVersion = "1.0.0" - } - } -} +//compose.desktop { +//} + + +application { +mainClass = "com.handstandsam.shoppingapp.compose.MainKt" + +// nativeDistributions { +// targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) +// packageName = "ShoppingApp Desktop" +// packageVersion = "1.0.0" +// } +} \ No newline at end of file diff --git a/desktop/src/jvmMain/kotlin/com/handstandsam/shoppingapp/compose/Main.kt b/desktop/src/jvmMain/kotlin/com/handstandsam/shoppingapp/compose/Main.kt deleted file mode 100644 index 3ac6c848..00000000 --- a/desktop/src/jvmMain/kotlin/com/handstandsam/shoppingapp/compose/Main.kt +++ /dev/null @@ -1,208 +0,0 @@ -@file:OptIn(ExperimentalMaterialApi::class) - -package com.handstandsam.shoppingapp.compose - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.window.Window -import androidx.compose.ui.window.WindowPosition -import androidx.compose.ui.window.application -import androidx.compose.ui.window.rememberWindowState -import com.handstandsam.shoppingapp.cart.InMemoryShoppingCartDao -import com.handstandsam.shoppingapp.cart.SessionManager -import com.handstandsam.shoppingapp.cart.ShoppingCart -import com.handstandsam.shoppingapp.di.NetworkGraph -import com.handstandsam.shoppingapp.features.category.CategoryViewModel -import com.handstandsam.shoppingapp.features.checkout.ShoppingCartViewModel -import com.handstandsam.shoppingapp.features.home.HomeViewModel -import com.handstandsam.shoppingapp.mockdata.ProduceMockAccount -import com.handstandsam.shoppingapp.models.Category -import com.handstandsam.shoppingapp.models.Item -import com.handstandsam.shoppingapp.models.LoginRequest -import com.handstandsam.shoppingapp.models.User -import com.handstandsam.shoppingapp.network.Response -import com.handstandsam.shoppingapp.repository.CategoryRepo -import com.handstandsam.shoppingapp.repository.ItemRepo -import com.handstandsam.shoppingapp.repository.UserRepo -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch - -object DesktopAppGraph { - val shoppingCart = ShoppingCart(InMemoryShoppingCartDao()) - val scope = CoroutineScope(Dispatchers.IO) - - val sessionManager = object : SessionManager { - override val currentUser: MutableStateFlow = MutableStateFlow( - User( - firstname = "Desktop", lastname = "User" - ) - ) - override val isLoggedIn: Boolean = currentUser.value != null - - override fun updateCurrentUser(user: User?) { - currentUser.value = user - } - - override suspend fun logout() { - updateCurrentUser(null) - } - } - - val mockAccount = ProduceMockAccount() - val networkGraph = object : NetworkGraph { - override val categoryRepo: CategoryRepo = - object : CategoryRepo { - override suspend fun getCategories(): Response> { - val categories = mockAccount.getCategories() - return Response.Success(categories) - } - } - - override val itemRepo: ItemRepo = - object : ItemRepo { - override suspend fun getItemsForCategory(categoryLabel: String): Response> { - val itemsForCategory = mockAccount.getItemsForCategory(categoryLabel) - if (itemsForCategory != null) { - return Response.Success(itemsForCategory) - } else { - return Response.Failure() - } - } - } - - override val userRepo: UserRepo = - object : UserRepo { - override suspend fun login(loginRequest: LoginRequest): Response { - return Response.Success(mockAccount.getUser()) - } - } - } -} - -enum class ScreenType { - Home, Category, Cart -} - -fun main() { - - val scope = DesktopAppGraph.scope - val shoppingCart = DesktopAppGraph.shoppingCart - val sessionManager = DesktopAppGraph.sessionManager - val categoryRepo = DesktopAppGraph.networkGraph.categoryRepo - val itemRepo = DesktopAppGraph.networkGraph.itemRepo - - val basicNav = MutableStateFlow(ScreenType.Home) - - @Composable - fun ShoppingCartPage() { - val shoppingCartViewModel = ShoppingCartViewModel(scope, shoppingCart) - ShoppingCartScreen( - itemsInCart = shoppingCart.itemsInCart, - homeUpClicked = { - basicNav.value = ScreenType.Home - }, - checkoutClicked = {}, - logoutClicked = {}, - shoppingCartViewModel = shoppingCartViewModel, - shoppingAppImageLoader = DesktopShoppingAppImageLoader() - ) - } - - val categoryViewModel = CategoryViewModel( - scope = scope, - itemRepo = itemRepo, - ) - - @Composable - fun CategoryPage() { - CategoryScreen( - itemsInCart = shoppingCart.itemsInCart, - logoutClicked = {}, - shoppingAppImageLoader = DesktopShoppingAppImageLoader(), - categoryViewModel = categoryViewModel, - showCartClicked = { - basicNav.value = ScreenType.Cart - }, - homeUpClicked = { - basicNav.value = ScreenType.Home - }, - itemClicked = { item -> - scope.launch { - shoppingCart.incrementItemInCart(item) - basicNav.value = ScreenType.Cart - } - } - ) - } - - val homeViewModel = HomeViewModel( - scope, - sessionManager, - categoryRepo - ).apply { - scope.launch { - sideEffects - .onEach { homeViewModelSideEffect -> - when (homeViewModelSideEffect) { - is HomeViewModel.SideEffect.LaunchCategoryActivity -> { - categoryViewModel.send(CategoryViewModel.Intention.CategoryLabelSet(homeViewModelSideEffect.category.label)) - basicNav.value = ScreenType.Category - } - - HomeViewModel.SideEffect.Logout -> TODO() - } - } - .collect() - } - } - - @Composable - fun HomePage() { - HomeScreen( - itemsInCart = shoppingCart.itemsInCart, - logoutClicked = {}, - shoppingAppImageLoader = DesktopShoppingAppImageLoader(), - homeViewModel = homeViewModel, - showCartClicked = { - basicNav.value = ScreenType.Cart - } - ) - } - - @Composable - fun CurrentScreen() { - val curr = basicNav.collectAsState() - when (curr.value) { - ScreenType.Home -> HomePage() - ScreenType.Category -> CategoryPage() - ScreenType.Cart -> ShoppingCartPage() - } - } - application { - Window( - onCloseRequest = ::exitApplication, - title = "ShoppingApp Desktop", - state = rememberWindowState( - position = WindowPosition(alignment = Alignment.Center), - ), - ) { - MaterialTheme { - Box( - modifier = Modifier.fillMaxSize() - ) { - CurrentScreen() - } - } - } - } -} \ No newline at end of file diff --git a/desktop/src/jvmMain/kotlin/com/handstandsam/shoppingapp/compose/DesktopShoppingAppImageLoader.kt b/desktop/src/main/kotlin/com/handstandsam/shoppingapp/compose/DesktopShoppingAppImageLoader.kt similarity index 100% rename from desktop/src/jvmMain/kotlin/com/handstandsam/shoppingapp/compose/DesktopShoppingAppImageLoader.kt rename to desktop/src/main/kotlin/com/handstandsam/shoppingapp/compose/DesktopShoppingAppImageLoader.kt diff --git a/desktop/src/main/kotlin/com/handstandsam/shoppingapp/compose/Main.kt b/desktop/src/main/kotlin/com/handstandsam/shoppingapp/compose/Main.kt new file mode 100644 index 00000000..59c7ddc9 --- /dev/null +++ b/desktop/src/main/kotlin/com/handstandsam/shoppingapp/compose/Main.kt @@ -0,0 +1,245 @@ +@file:OptIn(ExperimentalMaterialApi::class) + +package com.handstandsam.shoppingapp.compose + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.Button +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Window +import androidx.compose.ui.window.WindowPosition +import androidx.compose.ui.window.application +import androidx.compose.ui.window.rememberWindowState +import com.handstandsam.shoppingapp.cart.InMemoryShoppingCartDao +import com.handstandsam.shoppingapp.cart.SessionManager +import com.handstandsam.shoppingapp.cart.ShoppingCart +import com.handstandsam.shoppingapp.di.NetworkGraph +import com.handstandsam.shoppingapp.features.category.CategoryViewModel +import com.handstandsam.shoppingapp.features.checkout.ShoppingCartViewModel +import com.handstandsam.shoppingapp.features.home.HomeViewModel +import com.handstandsam.shoppingapp.mockdata.ProduceMockAccount +import com.handstandsam.shoppingapp.models.Category +import com.handstandsam.shoppingapp.models.Item +import com.handstandsam.shoppingapp.models.LoginRequest +import com.handstandsam.shoppingapp.models.User +import com.handstandsam.shoppingapp.network.Response +import com.handstandsam.shoppingapp.repository.CategoryRepo +import com.handstandsam.shoppingapp.repository.ItemRepo +import com.handstandsam.shoppingapp.repository.UserRepo +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch + +object DesktopAppGraph { + val shoppingCart = ShoppingCart(InMemoryShoppingCartDao()) + val scope = CoroutineScope(Dispatchers.IO) + + val sessionManager = object : SessionManager { + override val currentUser: MutableStateFlow = MutableStateFlow( + User( + firstname = "Desktop", lastname = "User" + ) + ) + override val isLoggedIn: Boolean = currentUser.value != null + + override fun updateCurrentUser(user: User?) { + currentUser.value = user + } + + override suspend fun logout() { + updateCurrentUser(null) + } + } + + val mockAccount = ProduceMockAccount() + val networkGraph = object : NetworkGraph { + override val categoryRepo: CategoryRepo = + object : CategoryRepo { + override suspend fun getCategories(): Response> { + val categories = mockAccount.getCategories() + return Response.Success(categories) + } + } + + override val itemRepo: ItemRepo = + object : ItemRepo { + override suspend fun getItemsForCategory(categoryLabel: String): Response> { + val itemsForCategory = mockAccount.getItemsForCategory(categoryLabel) + if (itemsForCategory != null) { + return Response.Success(itemsForCategory) + } else { + return Response.Failure() + } + } + } + + override val userRepo: UserRepo = + object : UserRepo { + override suspend fun login(loginRequest: LoginRequest): Response { + return Response.Success(mockAccount.getUser()) + } + } + } +} + +enum class ScreenType { + Home, Category, Cart +} + +val scope = DesktopAppGraph.scope +val shoppingCart = DesktopAppGraph.shoppingCart +val sessionManager = DesktopAppGraph.sessionManager +val categoryRepo = DesktopAppGraph.networkGraph.categoryRepo +val itemRepo = DesktopAppGraph.networkGraph.itemRepo + +val basicNav = MutableStateFlow(ScreenType.Home) + +fun main1() = application { + + Window( + onCloseRequest = ::exitApplication, + title = "ShoppingApp Desktop", + state = rememberWindowState( + position = WindowPosition(alignment = Alignment.Center), + ), + ) { + MaterialTheme { + Box( + modifier = Modifier.fillMaxSize() + ) { + CurrentScreen() + } + } + } +} + +fun main() = application { + Window( + onCloseRequest = ::exitApplication, + title = "Compose for Desktop", + state = rememberWindowState(width = 300.dp, height = 300.dp) + ) { + val count = remember { mutableStateOf(0) } + MaterialTheme { + Column(Modifier.fillMaxSize(), Arrangement.spacedBy(5.dp)) { + Button(modifier = Modifier.align(Alignment.CenterHorizontally), + onClick = { + count.value++ + }) { + Text(if (count.value == 0) "Hello World" else "Clicked ${count.value}!") + } + Button(modifier = Modifier.align(Alignment.CenterHorizontally), + onClick = { + count.value = 0 + }) { + Text("Reset") + } + } + } + } +} + + +@Composable +fun ShoppingCartPage() { + val shoppingCartViewModel = ShoppingCartViewModel(scope, shoppingCart) + ShoppingCartScreen( + itemsInCart = shoppingCart.itemsInCart, + homeUpClicked = { + basicNav.value = ScreenType.Home + }, + checkoutClicked = {}, + logoutClicked = {}, + shoppingCartViewModel = shoppingCartViewModel, + shoppingAppImageLoader = DesktopShoppingAppImageLoader() + ) +} + +val categoryViewModel = CategoryViewModel( + scope = scope, + itemRepo = itemRepo, +) + +@Composable +fun CategoryPage() { + CategoryScreen( + itemsInCart = shoppingCart.itemsInCart, + logoutClicked = {}, + shoppingAppImageLoader = DesktopShoppingAppImageLoader(), + categoryViewModel = categoryViewModel, + showCartClicked = { + basicNav.value = ScreenType.Cart + }, + homeUpClicked = { + basicNav.value = ScreenType.Home + }, + itemClicked = { item -> + scope.launch { + shoppingCart.incrementItemInCart(item) + basicNav.value = ScreenType.Cart + } + } + ) +} + +val homeViewModel = HomeViewModel( + scope, + sessionManager, + categoryRepo +).apply { + scope.launch { + sideEffects + .onEach { homeViewModelSideEffect -> + when (homeViewModelSideEffect) { + is HomeViewModel.SideEffect.LaunchCategoryActivity -> { + categoryViewModel.send( + CategoryViewModel.Intention.CategoryLabelSet( + homeViewModelSideEffect.category.label + ) + ) + basicNav.value = ScreenType.Category + } + + HomeViewModel.SideEffect.Logout -> TODO() + } + } + .collect() + } +} + +@Composable +fun HomePage() { + HomeScreen( + itemsInCart = shoppingCart.itemsInCart, + logoutClicked = {}, + shoppingAppImageLoader = DesktopShoppingAppImageLoader(), + homeViewModel = homeViewModel, + showCartClicked = { + basicNav.value = ScreenType.Cart + } + ) +} + +@Composable +fun CurrentScreen() { + val curr = basicNav.collectAsState() + when (curr.value) { + ScreenType.Home -> HomePage() + ScreenType.Category -> CategoryPage() + ScreenType.Cart -> ShoppingCartPage() + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 9fb4e54c..3fa4c51f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,9 +27,9 @@ kotlin.mpp.stability.nowarn=true kotlin.mpp.enableCInteropCommonization=true # KMP4FREE -kmp4free=true +kmp4free=false ios=false -js=true +js=false # Temp property to not have to upgrade AGP for now android.suppressUnsupportedCompileSdk=34 \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 55bee498..1dd39b28 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,17 +15,19 @@ androidx_test_runner = "1.5.2" apache_commons = "2.11.0" assertj = "3.23.1" coil_compose = "2.2.0" -compose = "1.5.12" -compose_compiler = "1.5.3" +compose = "1.6.8" + + + dependency_guard = "0.5.0" espresso = "3.5.1" glide = "4.11.0" -jetbrains_compose = "1.5.12" +jetbrains_compose = "1.6.11" junit = "4.13.2" kmp4free = "0.1.0" -kotlin = "1.9.22" -kotlin_coroutines = "1.7.3" -kotlinx_serialization = "1.6.0" +kotlin = "2.0.0" +kotlin_coroutines = "1.8.1" +kotlinx_serialization = "1.7.1" ktor = "2.1.0" ktor_client_okhttp = "2.1.0" okhttp = "4.11.0" @@ -42,7 +44,6 @@ assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" } accompanist_coil = { module = "com.google.accompanist:accompanist-coil", version.ref = "accompanist_coil" } androidx_activity_compose = { module = "androidx.activity:activity-compose", version.ref = "androidx_activity" } androidx_appcompat_v7 = { module = "androidx.appcompat:appcompat", version.ref = "androidx_appcompat" } -androidx_compose_compiler = { module = "androidx.compose.compiler:compiler", version.ref = "compose_compiler" } androidx_compose_runtime = { module = "androidx.compose.runtime:runtime", version.ref = "compose" } androidx_compose_ui = { module = "androidx.compose.ui:ui", version.ref = "compose" } androidx_compose_foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose" } @@ -66,7 +67,6 @@ androidx_test_rules = { module = "androidx.test:rules", version.ref = "androidx_ androidx_test_orchestrator = { module = "androidx.test:orchestrator", version.ref = "androidx_test_orchestrator" } coil_compose = { module = "io.coil-kt:coil-compose", version.ref = "coil_compose" } glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" } -jetbrains_compose_gradle_plugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "jetbrains_compose" } jetbrains_compose_web_core = { module = "org.jetbrains.compose.web:web-core", version.ref = "jetbrains_compose" } jetbrains_compose_runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "jetbrains_compose" } junit = { module = "junit:junit", version.ref = "junit" } @@ -97,3 +97,7 @@ timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } [plugins] dependency_guard = { id = "com.dropbox.dependency-guard", version.ref = "dependency_guard" } kmp4free = { id = "com.handstandsam.kmp4free", version.ref = "kmp4free" } +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +jetbrains-compose = { id = "org.jetbrains.compose", version.ref = "jetbrains_compose" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 48c0a02c..0d184210 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/multiplatform/build.gradle.kts b/multiplatform/build.gradle.kts index 6bb55ab2..1ff115f3 100644 --- a/multiplatform/build.gradle.kts +++ b/multiplatform/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("multiplatform") + alias(libs.plugins.kotlin.multiplatform) } val useKmp4Free = findProperty("kmp4free") == "true" val useIos = findProperty("ios") == "true"