From a55c5995ebcf1655bd66e25282a1156e1ac64672 Mon Sep 17 00:00:00 2001 From: Mads Mogensen Date: Thu, 4 Apr 2024 11:30:50 +0200 Subject: [PATCH] Setup project for Jetpack Compose Add CI Lint with ktlint All gradle files now use kotlin for configuring. Change libraries for Jetpack Compose Change main activity to Jetpack Compose Fix build error --- .editorconfig | 2 + .github/workflows/gradle.yml | 45 ++++++++ app/build.gradle.kts | 84 ++++++++++++++ app/{build.gradle => build.gradle.orig} | 0 app/proguard-rules.pro | 2 +- .../ExampleInstrumentedTest.kt | 13 ++- app/src/main/AndroidManifest.xml | 4 +- .../schedulingfrontend/MainActivity.kt | 67 +++++++----- .../{API => api}/ApiClient.kt | 27 +++-- .../{API => api}/ApiService.kt | 6 +- .../schedulingfrontend/loginpage/LoginPage.kt | 103 +++++++++++------- .../schedulingfrontend/ui/theme/Color.kt | 11 ++ .../schedulingfrontend/ui/theme/Theme.kt | 72 ++++++++++++ .../schedulingfrontend/ui/theme/Type.kt | 36 ++++++ .../ic_launcher_foreground.xml | 0 app/src/main/res/layout/activity_main.xml | 30 ----- .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 - .../ic_launcher.xml | 0 .../ic_launcher_round.xml | 1 + app/src/main/res/values-night/themes.xml | 16 --- app/src/main/res/values/themes.xml | 18 +-- .../schedulingfrontend/ExampleUnitTest.kt | 9 +- build.gradle | 6 - build.gradle.kts | 5 + gradle.properties | 2 - 25 files changed, 400 insertions(+), 164 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/workflows/gradle.yml create mode 100644 app/build.gradle.kts rename app/{build.gradle => build.gradle.orig} (100%) rename app/src/main/java/dk/scheduling/schedulingfrontend/{API => api}/ApiClient.kt (69%) rename app/src/main/java/dk/scheduling/schedulingfrontend/{API => api}/ApiService.kt (53%) create mode 100644 app/src/main/java/dk/scheduling/schedulingfrontend/ui/theme/Color.kt create mode 100644 app/src/main/java/dk/scheduling/schedulingfrontend/ui/theme/Theme.kt create mode 100644 app/src/main/java/dk/scheduling/schedulingfrontend/ui/theme/Type.kt rename app/src/main/res/{drawable-v24 => drawable}/ic_launcher_foreground.xml (100%) delete mode 100644 app/src/main/res/layout/activity_main.xml delete mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename app/src/main/res/{mipmap-anydpi-v33 => mipmap-anydpi}/ic_launcher.xml (100%) rename app/src/main/res/{mipmap-anydpi-v26 => mipmap-anydpi}/ic_launcher_round.xml (79%) delete mode 100644 app/src/main/res/values-night/themes.xml delete mode 100644 build.gradle create mode 100644 build.gradle.kts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6158e4d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,2 @@ +[*{kt,kts}] +ktlint_function_naming_ignore_when_annotated_with=Composable diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..55d4658 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,45 @@ +name: Java CI with Gradle + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Enable KVM + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + - uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: '21' + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + - name: Build with Gradle + run: ./gradlew build + - name: Test (local) + run: ./gradlew test + - name: Test (emulator) + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 29 + script: ./gradlew connectedCheck + - name: Android Test Report + uses: asadmansr/android-test-report-action@v1.2.0 + if: ${{ always() }} # IMPORTANT: run Android Test Report regardless + - name: Lint + run: | + ./gradlew lint + ./gradlew ktlintCheck diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..67c3e64 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,84 @@ +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + id("org.jlleitschuh.gradle.ktlint") version "12.1.0" +} + +android { + namespace = "dk.scheduling.schedulingfrontend" + compileSdk = 34 + + defaultConfig { + applicationId = "dk.scheduling.schedulingfrontend" + minSdk = 28 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro", + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = "1.5.11" + } + + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") + implementation("androidx.activity:activity-compose:1.8.2") + implementation(platform("androidx.compose:compose-bom:2024.04.00")) + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.ui:ui-graphics") + implementation("androidx.compose.ui:ui-tooling-preview") + implementation("androidx.compose.material3:material3") + implementation("androidx.compose.material:material-icons-core") + implementation("androidx.compose.material:material-icons-extended") + implementation("org.apache.commons:commons-lang3:3.14.0") + implementation("com.squareup.retrofit2:retrofit:2.9.0") + implementation("com.squareup.retrofit2:converter-gson:2.9.0") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + androidTestImplementation(platform("androidx.compose:compose-bom:2024.04.00")) + androidTestImplementation("androidx.compose.ui:ui-test-junit4") + debugImplementation("androidx.compose.ui:ui-tooling") + debugImplementation("androidx.compose.ui:ui-test-manifest") +} + +ktlint { + dependencies { + ktlintRuleset("com.twitter.compose.rules:ktlint:0.0.26") + } +} diff --git a/app/build.gradle b/app/build.gradle.orig similarity index 100% rename from app/build.gradle rename to app/build.gradle.orig diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb43..ff59496 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/app/src/androidTest/java/dk/scheduling/schedulingfrontend/ExampleInstrumentedTest.kt b/app/src/androidTest/java/dk/scheduling/schedulingfrontend/ExampleInstrumentedTest.kt index 453cb20..9696866 100644 --- a/app/src/androidTest/java/dk/scheduling/schedulingfrontend/ExampleInstrumentedTest.kt +++ b/app/src/androidTest/java/dk/scheduling/schedulingfrontend/ExampleInstrumentedTest.kt @@ -1,11 +1,12 @@ +@file:Suppress("ktlint:standard:no-wildcard-imports") + package dk.scheduling.schedulingfrontend -import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.runner.RunWith - +import androidx.test.platform.app.InstrumentationRegistry import org.junit.Assert.* +import org.junit.Test +import org.junit.runner.RunWith /** * Instrumented test, which will execute on an Android device. @@ -14,10 +15,10 @@ import org.junit.Assert.* */ @RunWith(AndroidJUnit4::class) class ExampleInstrumentedTest { - @org.junit.jupiter.api.Test + @Test fun useAppContext() { // Context of the app under test. val appContext = InstrumentationRegistry.getInstrumentation().targetContext assertEquals("dk.scheduling.schedulingfrontend", appContext.packageName) } -} \ No newline at end of file +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 30dbb70..d5d9bd2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,13 +9,15 @@ android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.SchedulingFrontend" android:usesCleartextTraffic="true" tools:targetApi="31"> + android:exported="true" + android:theme="@style/Theme.SchedulingFrontend"> diff --git a/app/src/main/java/dk/scheduling/schedulingfrontend/MainActivity.kt b/app/src/main/java/dk/scheduling/schedulingfrontend/MainActivity.kt index f1bdbf2..107372e 100644 --- a/app/src/main/java/dk/scheduling/schedulingfrontend/MainActivity.kt +++ b/app/src/main/java/dk/scheduling/schedulingfrontend/MainActivity.kt @@ -1,39 +1,56 @@ package dk.scheduling.schedulingfrontend -import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log -import android.util.Log.ERROR -import android.widget.Button -import dk.scheduling.schedulingfrontend.API.ApiClient +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Text +import dk.scheduling.schedulingfrontend.api.ApiClient +import dk.scheduling.schedulingfrontend.ui.theme.SchedulingFrontendTheme import retrofit2.Call import retrofit2.Callback import retrofit2.Response -class MainActivity : AppCompatActivity() { + +class MainActivity : ComponentActivity() { + @OptIn(ExperimentalMaterial3Api::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - val button = findViewById