diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/android/.gitignore @@ -0,0 +1 @@ +/build diff --git a/android/build.gradle.kts b/android/build.gradle.kts new file mode 100644 index 0000000..6f0c665 --- /dev/null +++ b/android/build.gradle.kts @@ -0,0 +1,47 @@ +import org.jetbrains.kotlin.config.KotlinCompilerVersion + +plugins { + id("com.android.application") + id("kotlin-android") +} + +android { + compileSdkVersion(30) + + defaultConfig { + applicationId = "playground.android" + minSdkVersion(21) + targetSdkVersion(30) + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + named("release"){ + isMinifyEnabled = false + setProguardFiles(listOf(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + + implementation(Kotlin.stdlib) + implementation(AndroidX.core.ktx) + implementation(AndroidX.appCompat) + implementation(AndroidX.constraintLayout) + implementation(Google.android.material) + androidTestImplementation(AndroidX.test.ext.junit) + androidTestImplementation(AndroidX.test.espresso.core) + testImplementation(Testing.junit4) + implementation("app.cash.contour:contour:_") +} diff --git a/android/proguard-rules.pro b/android/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/android/proguard-rules.pro @@ -0,0 +1,21 @@ +# 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 diff --git a/android/src/androidTest/java/playground/android/ExampleInstrumentedTest.kt b/android/src/androidTest/java/playground/android/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..1c06398 --- /dev/null +++ b/android/src/androidTest/java/playground/android/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package playground.android + +import android.support.test.InstrumentationRegistry +import android.support.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("playground.android", appContext.packageName) + } +} diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..d469e08 --- /dev/null +++ b/android/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + diff --git a/android/src/main/java/playground/android/MainActivity.kt b/android/src/main/java/playground/android/MainActivity.kt new file mode 100644 index 0000000..5f3c6db --- /dev/null +++ b/android/src/main/java/playground/android/MainActivity.kt @@ -0,0 +1,13 @@ +package playground.android + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity + + +class MainActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(MainView(this)) + + } +} diff --git a/android/src/main/java/playground/android/MainView.kt b/android/src/main/java/playground/android/MainView.kt new file mode 100644 index 0000000..abd9fa8 --- /dev/null +++ b/android/src/main/java/playground/android/MainView.kt @@ -0,0 +1,87 @@ +package playground.android + +import android.content.Context +import android.graphics.Color +import android.graphics.Typeface +import android.text.InputType +import android.util.AttributeSet +import android.view.Gravity +import android.widget.Button +import android.widget.EditText +import android.widget.TextView +import androidx.core.view.updatePadding +import com.squareup.contour.ContourLayout + +class MainView(context: Context, attrs: AttributeSet? = null) : ContourLayout(context, attrs) { + private val toolbar = TextView(context).apply { + gravity = Gravity.CENTER_VERTICAL + letterSpacing = 0.05f + text = "Enter your details" + textSize = 18f + typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL) + setTextColor(Color.WHITE) + updatePadding(left = 26.dip) + } + private var name = EditText(context).apply { + hint = "Name" + textSize = 18f + typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL) + } + private var email = EditText(context).apply { + hint = "Email" + inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS + textSize = 18f + typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL) + } + var password = EditText(context).apply { + hint = "Password" + inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + textSize = 18f + typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL) + } + + private var confirmPassword = EditText(context).apply { + hint = "Confirm Password" + inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + textSize = 18f + typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL) + } + private val submitBtn = Button(context).apply { + text = "Submit" + setBackgroundResource(R.drawable.btn_shape) + + + } + + init { + + toolbar.layoutBy( + x = leftTo { parent.left() }, + y = topTo { parent.top() + 4.ydip }.heightOf { 56.ydip } + ) + name.layoutBy( + x = leftTo { parent.left() + 50.xdip }.rightTo { parent.right() - 10.xdip }, + y = bottomTo { toolbar.top() + 120.ydip } + ) + + email.layoutBy( + x = leftTo { parent.left() + 50.xdip }.rightTo { parent.right() - 10.xdip }, + y = bottomTo { name.bottom() + 60.ydip } + ) + + password.layoutBy( + x = leftTo { parent.left() + 50.xdip }.rightTo { parent.right() - 10.xdip }, + y = bottomTo { email.bottom() + 60.ydip } + + ) + confirmPassword.layoutBy( + x = leftTo { parent.left() + 50.xdip }.rightTo { parent.right() - 10.xdip }, + y = bottomTo { password.bottom() + 60.ydip } + + ) + submitBtn.layoutBy( + x = leftTo { parent.left() + 50.xdip }.rightTo { parent.right() - 100.xdip }, + y = bottomTo { confirmPassword.bottom() + 80.ydip } + ) + } +} diff --git a/android/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/android/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/android/src/main/res/drawable/btn_shape.xml b/android/src/main/res/drawable/btn_shape.xml new file mode 100644 index 0000000..4a401e2 --- /dev/null +++ b/android/src/main/res/drawable/btn_shape.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/android/src/main/res/drawable/ic_launcher_background.xml b/android/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/android/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/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/src/main/res/mipmap-hdpi/ic_launcher.png b/android/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a571e60 Binary files /dev/null and b/android/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..61da551 Binary files /dev/null and b/android/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/android/src/main/res/mipmap-mdpi/ic_launcher.png b/android/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..c41dd28 Binary files /dev/null and b/android/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..db5080a Binary files /dev/null and b/android/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/android/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6dba46d Binary files /dev/null and b/android/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..da31a87 Binary files /dev/null and b/android/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/android/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..15ac681 Binary files /dev/null and b/android/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..b216f2d Binary files /dev/null and b/android/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..f25a419 Binary files /dev/null and b/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..e96783c Binary files /dev/null and b/android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/android/src/main/res/values-night/themes.xml b/android/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..a823cb5 --- /dev/null +++ b/android/src/main/res/values-night/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/android/src/main/res/values/colors.xml b/android/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/android/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml new file mode 100644 index 0000000..fe84c89 --- /dev/null +++ b/android/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Playground Android + diff --git a/android/src/main/res/values/themes.xml b/android/src/main/res/values/themes.xml new file mode 100644 index 0000000..3fbed88 --- /dev/null +++ b/android/src/main/res/values/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/android/src/test/java/playground/android/ExampleUnitTest.kt b/android/src/test/java/playground/android/ExampleUnitTest.kt new file mode 100644 index 0000000..a286b41 --- /dev/null +++ b/android/src/test/java/playground/android/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package playground.android + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} diff --git a/build.gradle.kts b/build.gradle.kts index b719871..ba56279 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,18 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask +buildscript { + val kotlin_version by extra("1.5.10") + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle:_") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") + } +} + plugins { kotlin("jvm").apply(false) id("com.github.ben-manes.versions") diff --git a/gradle.properties b/gradle.properties index ae4d68f..91abd19 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,3 +2,7 @@ kotlin.code.style=official org.gradle.caching=true org.gradle.parallel=true + +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +android.useAndroidX=true +android.enableJetifier=true diff --git a/gradle/detekt-android-sdk.gradle b/gradle/detekt-android-sdk.gradle new file mode 100644 index 0000000..ef32a54 --- /dev/null +++ b/gradle/detekt-android-sdk.gradle @@ -0,0 +1,58 @@ +// https://github.com/mockk/mockk +def pathExists(String envPath) { + if (envPath != null && !envPath.empty) { + return file(envPath).exists() + } + + return false +} + +def setPropPath(Properties props, String prop, String path) { + if (!file(path).isDirectory()) return + if (props.hasProperty(prop)) return + props[prop] = path +} + +def propsPath = file("../local.properties") +def props = new Properties() + +if (propsPath.isFile()) { + props.load(new FileReader(propsPath)) +} + +ext.hasAndroidSdk = false +String newAndroidSdkPath = null +if (props.containsKey("sdk.dir")) { + ext.hasAndroidSdk = true +} else if (pathExists(System.env.ANDROID_HOME)) { + newAndroidSdkPath = System.env.ANDROID_HOME +} else if (pathExists(System.env.ANDROID_SDK_ROOT)) { + newAndroidSdkPath = System.env.ANDROID_SDK_ROOT +} else if (pathExists(System.env.HOME + "/Android/Sdk")) { + newAndroidSdkPath = System.env.HOME + "/Android/Sdk" +} + +if (newAndroidSdkPath != null) { + setPropPath(props, "sdk.dir", newAndroidSdkPath) + + def oldProps = new Properties(props) + + if (props != oldProps) { + def writer = new FileWriter(propsPath) + try { + props.store(writer, "generated by 'detect-android-sdk.gradle'") + } finally { + writer.close() + } + } + + ext.hasAndroidSdk = true +} + +if (ext.hasAndroidSdk != true){ + println '''\ +[WARNING] Skipping build of Android related modules because Android SDK has not been found! + Define Android SDK location in 'local.properties' file or with ANDROID_HOME + environment variable to build Android modules +''' +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 97c2907..ce321b4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,4 @@ +include(":android") pluginManagement { repositories { gradlePluginPortal() @@ -30,7 +31,9 @@ gradleEnterprise { rootProject.name = "kotlin-libraries-playground" - +apply(from= "gradle/detekt-android-sdk.gradle") +val hasAndroidSdk: Boolean by extra +if (hasAndroidSdk) include("android") include("kotlin-jvm") include("kotlin-testing") include("kotlin-codegen") diff --git a/versions.properties b/versions.properties index f544c64..35aa6d5 100644 --- a/versions.properties +++ b/versions.properties @@ -7,12 +7,50 @@ #### suppress inspection "SpellCheckingInspection" for whole file #### suppress inspection "UnusedProperty" for whole file +# Do not update because version 4.2.0 is not compatible with IntelliJ +plugin.android=4.1.1 + plugin.com.apollographql.apollo=2.5.7 plugin.com.github.ben-manes.versions=0.38.0 plugin.com.squareup.sqldelight=1.5.0 +version.androidx.appcompat=1.3.0 +## # available=1.4.0-alpha01 + +version.androidx.constraintlayout=2.0.4 +## # available=2.1.0-alpha1 +## # available=2.1.0-alpha2 +## # available=2.1.0-beta01 +## # available=2.1.0-beta02 + +version.androidx.core=1.5.0 +## # available=1.6.0-alpha01 +## # available=1.6.0-alpha02 +## # available=1.6.0-alpha03 +## # available=1.6.0-beta01 + +version.androidx.test.espresso=3.3.0 +## # available=3.4.0-alpha01 +## # available=3.4.0-alpha02 +## # available=3.4.0-alpha03 +## # available=3.4.0-alpha04 +## # available=3.4.0-alpha05 +## # available=3.4.0-alpha06 +## # available=3.4.0-beta01 + +version.androidx.test.ext.junit=1.1.2 +## # available=1.1.3-alpha01 +## # available=1.1.3-alpha02 +## # available=1.1.3-alpha03 +## # available=1.1.3-alpha04 +## # available=1.1.3-alpha05 +## # available=1.1.3-alpha06 +## # available=1.1.3-beta01 + +version.app.cash.contour..contour=1.1.0 + version.ch.tutteli.atrium..atrium-fluent-en_GB=0.16.0 version.com.apollographql.apollo..apollo-coroutines-support=2.5.7 @@ -52,6 +90,11 @@ version.com.tinder.statemachine..statemachine=0.2.0 version.com.uchuhimo..konf=1.1.2 +version.google.android.material=1.3.0 +## # available=1.4.0-alpha01 +## # available=1.4.0-alpha02 +## # available=1.4.0-beta01 + version.google.dagger=2.35.1 version.io.github.lucapiccinelli..konad=1.2.1 @@ -66,6 +109,8 @@ version.it.skrape..skrapeit-http-fetcher=1.1.1 version.junit=5.7.2 ### available=5.8.0-M1 +version.junit.junit=4.13.2 + version.kotest=4.4.3 ## # available=4.5.0.RC1 ## # available=4.5.0