diff --git a/kotlin-base/.gitignore b/kotlin-base/.gitignore new file mode 100644 index 0000000..90e5879 --- /dev/null +++ b/kotlin-base/.gitignore @@ -0,0 +1,13 @@ +.gradle +/local.properties +/.idea/workspace.xml +.DS_Store +.idea/ +*.iml +build/ +.gradletasknamecache + +crashlytics.properties +crashlytics-build.properties +com_crashlytics_export_strings.xml +dagger-proguard-keepnames.cfg \ No newline at end of file diff --git a/kotlin-base/.travis.yml b/kotlin-base/.travis.yml new file mode 100644 index 0000000..07dfa37 --- /dev/null +++ b/kotlin-base/.travis.yml @@ -0,0 +1,42 @@ +language: android +jdk: oraclejdk8 +sudo: false +env: + - GRADLE_OPTS='-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' + +machine: + environment: + GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' + +android: + components: + - tools + - platform-tools + - build-tools-25.0.1 + - android-25 + - extra-android-m2repository + # Uncomment this if you need emulator + # - sys-img-x86-android-23 + licenses: + - 'android-sdk-license-.+' + +before_install: + - export TERM=dumb + - chmod +x gradlew + +# Uncomment this if you need emulator +# before_script: +# - echo no | android create avd --force -n test -t android-21 --abi x86 +# - emulator -avd test -no-skin -no-audio -no-window & +# - android-wait-for-emulator +# - adb shell input keyevent 82 & + +script: + - ./gradlew checkstyle lintProductionRelease testProductionReleaseUnitTest + +branches: + only: + - master + - production + +# after_success: uncomment this and add your own deployment targets \ No newline at end of file diff --git a/kotlin-base/README.md b/kotlin-base/README.md new file mode 100644 index 0000000..a9043a7 --- /dev/null +++ b/kotlin-base/README.md @@ -0,0 +1,72 @@ +Android app skeleton +======================================= +## Continuous integration +* Travis CI [![Build Status](https://travis-ci.org/fs/android-base.png)](https://travis-ci.org/fs/android-base/pull_requests) +* Circle CI [![Build Status](https://circleci.com/gh/fs/android-base.png?style=shield&circle-token=c932b3e8650c436df970e9d1e9e06e8ef8fc9893)](https://circleci.com/gh/fs/android-base) + +##Prerequisites +* JDK 8 +* `JAVA_HOME` pointing to your jdk8 + +##Plugins for Android Studio for comfortable work +* [Parcelable generator](https://github.com/mcharmas/android-parcelable-intellij-plugin) + +##What's included: +* [Staging and Production](https://github.com/fs/android-base/blob/master/app/build.gradle#L29-L38) build flavors with different package names ([read more](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Product-flavors)) +* Logger configuration [supporting `Exception` logging](https://github.com/fs/android-base/blob/master/app/src/main/java/com/flatstack/android/App.java#L24-L26) ([read more](https://github.com/JakeWharton/timber)) +* [Robolectric support and configuration](https://github.com/fs/android-base/blob/master/app-tests/build.gradle) ([read more](http://blog.blundell-apps.com/android-gradle-app-with-robolectric-junit-tests/)) +* *Android Lint* [configuration](https://github.com/fs/android-base/blob/master/app/build.gradle#L56-L61) +* *Travis CI* and *CircleCI* build [script1](https://github.com/fs/android-base/blob/master/.travis.yml) [script2](https://github.com/fs/android-base/blob/master/circle.yml): + * Downloading an *Android SDK* + * Building + * Running *Android Lint* + * Running *Robolectric* tests + * Hook up your continuous deployment target in [`after_success`](https://github.com/fs/android-base/blob/master/.travis.yml#L40) for travis and in ['deployment'](https://github.com/fs/android-base/blob/master/circle.yml#L20) for CircleCi +* Release build signing and naming configuration + +##What's not included +* [Crashlytics](crashlytics.com): they live in their own world, and including their plugin in template project just fails the build, if `apikey` is not specified. Also, getting `apikey` without an IDE plugin is impossible. You can get it [here](https://crashlytics.com/downloads/android-studio) +* Test coverage: still in the process of figuring out what's the best way to enable unit test coverage for Android with Robolectric. Any suggestions will be highly appreciated + +##Setup + 1. Clone application as new project with original remote named "android-base" + + git clone --depth 1 git://github.com/fs/android-base.git --origin android-base [MY-NEW-PROJECT] + + **Note: we use depth parameter here in order to not copy the history of changes in base project** + + 2. Create your new repository on the GitHub and push master into it. Make sure master branch is tracking origin repo. + + cd [MY-NEW-PROJECT] + git remote add origin git@github.com:[MY-GITHUB-ACCOUNT]/[MY-NEW-PROJECT].git + git push -u origin master + + 3. Import the project into your favourite IDE (only [Android Studio](https://developer.android.com/sdk/installing/studio.html) and [IntelliJ IDEA](http://www.jetbrains.com/idea/) are supported). +Just select the root `build.gradle` and your IDE will do the rest. +It will ask you to change the language level - do it, we're using Java 8 now + +###Configuration +* Change your app's package by either [renaming the folder structure for Java sources](https://github.com/fs/android-base/tree/master/app/src/main/java/com/flatstack/android) or by just changing this [constant](https://github.com/fs/android-base/blob/master/app/build.gradle#L5) in `build.gradle` + +#Codestyles +Project contains default codestyle scheme at `./idea/codestyleSettings.xml`. Make sure that you use default project scheme to avoid mess with codestyle with your collegues. +Go to the Settings (`cmd + ,`) -> Editor -> Code Style look on top of right panel and select `Project` from `Scheme` dropdown. Apply -> Ok. + +###Making a release build +* Just uncomment [these lines](https://github.com/fs/android-base/blob/master/app/build.gradle#L41-L48) and fill them up with your credentials + +##Notes on ProGuarding +Project already has proguard config for included libraries. +If you add library check proguard section of documentation and update [proguard-rules.pro](https://github.com/fs/android-base/blob/master/app/proguard-rules.pr) + +##Notes on lambdas support: retrolambda and jack and Jill +Now Jack and Jil allow to use lambdas. Also it aims to speed up compilation process. +But it's buggy and does not support annotation processing (butterknife, greenrobot eventbus3, dagger use it). +When these drawbacks will be eliminated we move from retrolambda to jack&jill + +## Credits +Android app skeleton is maintained by [Adel Nizamutdinov](http://github.com/adelnizamutdinov) and [Ilya Eremin](http://github.com/ilyaeremin). +It was written by [Flatstack](http://www.flatstack.com) with the help of our +[contributors](http://github.com/fs/android-base/contributors) + +[](http://www.flatstack.com) diff --git a/kotlin-base/app/build.gradle b/kotlin-base/app/build.gradle new file mode 100644 index 0000000..8731263 --- /dev/null +++ b/kotlin-base/app/build.gradle @@ -0,0 +1,132 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'spoon' +apply from: 'checkstyle/checkstyle.gradle' + +apply from: '../deps.gradle' + +ext { + APPLICATION_ID = "com.flatstack.android" + isCI = "true".equals(System.getenv("CI")) + commitMessage = 'git log -1 --pretty=%B'.execute().text.trim() +} + +android { + compileSdkVersion versions.TARGET_SDK_VERSION + buildToolsVersion versions.BUILD_TOOLS_VERSION + + defaultConfig { + minSdkVersion versions.MIN_SDK_VERSION + targetSdkVersion versions.TARGET_SDK_VERSION + + applicationId APPLICATION_ID + versionCode 1 + versionName '1.0-beta' + testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner' + com.android.ddmlib.DdmPreferences.setTimeOut(60000) + } + + flavorDimensions "server" + + productFlavors { + staging { + buildConfigField "String", "API_URL", "\"https://example-staging.com\"" + applicationIdSuffix ".staging" + dimension "server" + } + + production { + buildConfigField "String", "API_URL", "\"https://example.com\"" + dimension "server" + } + } + +// signingConfigs { +// release { +// def props = new Properties() +// props.load(new FileInputStream(file("$rootDir/keys.properties"))) +// storeFile file("$rootDir/your.jks") +// storePassword props['storePassword'] +// keyAlias props['keyAlias'] +// keyPassword props['keyPassword'] +// } +// } + + buildTypes { + debug { + } + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + dexOptions { + preDexLibraries = !isCI + } + + packagingOptions { + exclude 'META-INF/LICENSE' + exclude 'META-INF/NOTICE' + exclude 'META-INF/services/javax.annotation.processing.Processor' + } + + lintOptions { + textReport true + textOutput "stdout" + lintConfig file("$projectDir/lint.xml") + warningsAsErrors true + } + + configurations.all { +// resolutionStrategy.force "com.android.support:support-annotations:$versions.support" + } +} + +repositories { + mavenCentral() +} + +dependencies { + compile supportLibs + compile rxJavaLibs +// compile retrofitLibs +// compile okHttpLibs + + compile 'com.google.code.gson:gson:2.4' + compile 'com.jakewharton:butterknife:7.0.0' // view injection + annotationProcessor 'com.jakewharton:butterknife:7.0.0' // view injection + kapt 'com.jakewharton:butterknife:7.0.0' // view injection + compile 'com.github.bumptech.glide:glide:3.7.0' + + testCompile unitTestLibs + androidTestCompile androidTestsLibs + compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" +} + +// Grant animation permissions to avoid test failure because of ui sync. +task grantAnimationPermissions(type: Exec, dependsOn: ['installStagingDebug', 'installProductionDebug']) { + group = 'test' + description = 'Grant permissions for testing.' + + def absolutePath = file('..') // Get project absolute path + commandLine "$absolutePath/app/set_animation_permissions.sh com.flatstack.android".split(" ") +} + +// Source: http://stackoverflow.com/q/29908110/112705 +afterEvaluate { + // When launching individual tests from Android Studio, it seems that only the assemble tasks + // get called directly, not the install* versions + tasks.each { task -> + if (task.name.endsWith('AndroidTest')) { + task.dependsOn grantAnimationPermissions + } + } +} + +apply from: "quality.gradle" \ No newline at end of file diff --git a/kotlin-base/app/checkstyle/checkstyle.gradle b/kotlin-base/app/checkstyle/checkstyle.gradle new file mode 100644 index 0000000..a384942 --- /dev/null +++ b/kotlin-base/app/checkstyle/checkstyle.gradle @@ -0,0 +1,17 @@ +apply plugin: 'checkstyle' + +check.dependsOn 'checkstyle' + +checkstyle { + toolVersion '6.5' + + configFile file("checkstyle/checkstyle.xml") + configProperties.checkstyleSuppressionFilterPath = file("checkstyle/suppressions.xml") + .absolutePath +} +task checkstyle(type: Checkstyle, group: 'verification') { + source 'src' + include '**/*.java' + exclude '**/gen/**' + classpath = files() +} \ No newline at end of file diff --git a/kotlin-base/app/checkstyle/checkstyle.xml b/kotlin-base/app/checkstyle/checkstyle.xml new file mode 100644 index 0000000..ae78e69 --- /dev/null +++ b/kotlin-base/app/checkstyle/checkstyle.xml @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-base/app/checkstyle/suppressions.xml b/kotlin-base/app/checkstyle/suppressions.xml new file mode 100644 index 0000000..7880252 --- /dev/null +++ b/kotlin-base/app/checkstyle/suppressions.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-base/app/findbugs-exclude.xml b/kotlin-base/app/findbugs-exclude.xml new file mode 100644 index 0000000..acdff83 --- /dev/null +++ b/kotlin-base/app/findbugs-exclude.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/kotlin-base/app/lint.xml b/kotlin-base/app/lint.xml new file mode 100644 index 0000000..840a880 --- /dev/null +++ b/kotlin-base/app/lint.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kotlin-base/app/proguard-rules.pro b/kotlin-base/app/proguard-rules.pro new file mode 100644 index 0000000..7a6d45d --- /dev/null +++ b/kotlin-base/app/proguard-rules.pro @@ -0,0 +1,65 @@ +#your models +#if you store all model under one package then use: +# -keep class your.package.name.models.** { *; } +#if you store models under different models packages then use: +#-keep class **.models.** { *; } + +#retrolambda +-dontwarn java.lang.invoke.* + +#butterknife +-keep class butterknife.** { *; } +-dontwarn butterknife.internal.** +-keep class **$$ViewBinder { *; } +-keepclasseswithmembernames class * { + @butterknife.* ; +} +-keepclasseswithmembernames class * { + @butterknife.* ; +} + +#picasso +-dontwarn com.squareup.okhttp3.** + +# OkHttp +-keepattributes Signature +-keepattributes *Annotation* +-keep class com.squareup.okhttp3.** { *; } +-keep interface com.squareup.okhttp3.** { *; } +-dontwarn com.squareup.okhttp3.** + +#rxjava +-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { + long producerIndex; + long consumerIndex; +} +-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { + rx.internal.util.atomic.LinkedQueueNode producerNode; +} +-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { + rx.internal.util.atomic.LinkedQueueNode consumerNode; +} +-dontwarn sun.misc.Unsafe + +#start gson +-keepattributes Signature +# For using GSON @Expose annotation +-keepattributes *Annotation* + +# Gson specific classes +-keep class sun.misc.Unsafe { *; } +#end of gson + +#glide +-keep public class * implements com.bumptech.glide.module.GlideModule +-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { + **[] $VALUES; + public *; +} + +#debug +-renamesourcefileattribute SourceFile +-keepattributes SourceFile,LineNumberTable + + + diff --git a/kotlin-base/app/quality.gradle b/kotlin-base/app/quality.gradle new file mode 100644 index 0000000..df2568d --- /dev/null +++ b/kotlin-base/app/quality.gradle @@ -0,0 +1,20 @@ +apply plugin: 'findbugs' + +final classesDir = "build/intermediates/classes/production/debug" +final sourceDir = "src/main/java" + +task findBugs(type: FindBugs, dependsOn: "assembleProductionDebug") { + classes = fileTree(classesDir) + source = fileTree(sourceDir) + classpath = files() + excludeFilter = file("findbugs-exclude.xml") + + effort = 'max' + + reports { + xml.enabled = false + html.enabled = true + } +} + +tasks.check.dependsOn findBugs diff --git a/kotlin-base/app/set_animation_permissions.sh b/kotlin-base/app/set_animation_permissions.sh new file mode 100755 index 0000000..b25127e --- /dev/null +++ b/kotlin-base/app/set_animation_permissions.sh @@ -0,0 +1,15 @@ +adb=$ANDROID_HOME/platform-tools/adb +package=$1 + +if [ "$#" = 0 ]; then + echo "No parameters found, run with sh set_animation_permissions.sh " + exit 0 +fi + +# get all the devices +devices=$($adb devices | grep -v 'List of devices' | cut -f1 | grep '.') + +for device in $devices; do + echo "Setting permissions to device" $device "for package" $package + $adb -s $device shell pm grant $package android.permission.SET_ANIMATION_SCALE +done \ No newline at end of file diff --git a/kotlin-base/app/src/androidTest/AndroidManifest.xml b/kotlin-base/app/src/androidTest/AndroidManifest.xml new file mode 100644 index 0000000..899bbbc --- /dev/null +++ b/kotlin-base/app/src/androidTest/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/kotlin-base/app/src/androidTest/java/com/flatstack/android/MainScreenTest.java b/kotlin-base/app/src/androidTest/java/com/flatstack/android/MainScreenTest.java new file mode 100644 index 0000000..f5b74cb --- /dev/null +++ b/kotlin-base/app/src/androidTest/java/com/flatstack/android/MainScreenTest.java @@ -0,0 +1,34 @@ +package com.flatstack.android; + +import android.support.test.runner.AndroidJUnit4; + +import com.flatstack.android.main_screen.MainActivity; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static org.hamcrest.Matchers.allOf; + +/** + * Created by ereminilya on 6/4/17. + */ + +@RunWith(AndroidJUnit4.class) +public class MainScreenTest { + + @Rule + public ScreenshotActivityRule testRule = + new ScreenshotActivityRule<>(MainActivity.class); + + @Test + public void whenAppLaunch_androidBaseVisible() throws Exception { + onView(allOf(withId(R.id.title), withText(R.string.app_name))) + .check(matches(isDisplayed())); + } +} \ No newline at end of file diff --git a/kotlin-base/app/src/androidTest/java/com/flatstack/android/ScreenshotActivityRule.java b/kotlin-base/app/src/androidTest/java/com/flatstack/android/ScreenshotActivityRule.java new file mode 100644 index 0000000..9e3f182 --- /dev/null +++ b/kotlin-base/app/src/androidTest/java/com/flatstack/android/ScreenshotActivityRule.java @@ -0,0 +1,37 @@ +package com.flatstack.android; + +import android.app.Activity; +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.espresso.Espresso; +import android.support.test.espresso.base.DefaultFailureHandler; +import android.support.test.rule.ActivityTestRule; + +import com.squareup.spoon.Spoon; + +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * Created by ereminilya on 6/4/17. + */ + +public class ScreenshotActivityRule extends ActivityTestRule { + + public ScreenshotActivityRule(Class activityClass) { + super(activityClass); + } + + @Override + public Statement apply(Statement base, Description description) { + String testClassName = description.getClassName(); + String testMethodName = description.getMethodName(); + Context context = InstrumentationRegistry.getTargetContext(); + Espresso.setFailureHandler((error, matcher) -> { + Spoon.screenshot(getActivity(), "failure", testClassName, testMethodName); + new DefaultFailureHandler(context).handle(error, matcher); + }); + return super.apply(base, description); + } + +} diff --git a/kotlin-base/app/src/main/AndroidManifest.xml b/kotlin-base/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..d0ee39f --- /dev/null +++ b/kotlin-base/app/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + diff --git a/kotlin-base/app/src/main/ic_launcher-web.png b/kotlin-base/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000..5c63bc5 Binary files /dev/null and b/kotlin-base/app/src/main/ic_launcher-web.png differ diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/App.kt b/kotlin-base/app/src/main/java/com/flatstack/android/App.kt new file mode 100644 index 0000000..e994a33 --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/App.kt @@ -0,0 +1,11 @@ +package com.flatstack.android + +import android.app.Application + +class App : Application() { + + override fun onCreate() { + super.onCreate() + // your super code here + } +} \ No newline at end of file diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/main_screen/MainActivity.kt b/kotlin-base/app/src/main/java/com/flatstack/android/main_screen/MainActivity.kt new file mode 100644 index 0000000..a9a9a8d --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/main_screen/MainActivity.kt @@ -0,0 +1,22 @@ +package com.flatstack.android.main_screen + +import android.os.Bundle + +import com.flatstack.android.utils.ui.BaseActivity +import com.flatstack.android.R +import com.flatstack.android.utils.ui.UiInfo + +class MainActivity : BaseActivity() { + + override val uiInfo = UiInfo(layoutRes = R.layout.activity_main, titleRes = R.string.app_name, + hasBackButton = true) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (savedInstanceState == null) { + supportFragmentManager.beginTransaction() + .replace(R.id.content, MainFragment()) + .commit() + } + } +} \ No newline at end of file diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/main_screen/MainFragment.kt b/kotlin-base/app/src/main/java/com/flatstack/android/main_screen/MainFragment.kt new file mode 100644 index 0000000..3fb87e6 --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/main_screen/MainFragment.kt @@ -0,0 +1,30 @@ +package com.flatstack.android.main_screen + +import android.os.Bundle +import android.view.View +import android.widget.ImageView +import butterknife.Bind +import com.bumptech.glide.Glide +import com.flatstack.android.R +import com.flatstack.android.utils.ui.BaseFragment + +class MainFragment : BaseFragment() { + + @Bind(R.id.image) @JvmField var image: ImageView? = null + + override val layoutRes = R.layout.fragment_main + + override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + image!!.setOnClickListener { listener -> + TestDialog.show("Example Hello", "Ublyudok, mat' tvoyu, a nu idi syuda, " + + "govno sobachye, reshil ko mne lezt'? Ti, zasranec vonyuchiy, mat' tvoyu, a?", + fragmentManager) + } + + Glide.with(this) + .load("https://pbs.twimg.com/profile_images/502109671600033792/QOAC0YGo.png") + .into(image!!) + } +} diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/main_screen/TestDialog.kt b/kotlin-base/app/src/main/java/com/flatstack/android/main_screen/TestDialog.kt new file mode 100644 index 0000000..f0dee1c --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/main_screen/TestDialog.kt @@ -0,0 +1,49 @@ +package com.flatstack.android.main_screen + +import android.os.Bundle +import android.support.v4.app.FragmentManager +import android.view.View +import android.widget.TextView +import butterknife.Bind +import com.flatstack.android.R +import com.flatstack.android.utils.ui.BaseDialogFragment + +class TestDialog : BaseDialogFragment() { + + @Bind(R.id.dialog_title) @JvmField var uiTitle: TextView? = null + @Bind(R.id.dialog_message) @JvmField var uiMessage: TextView? = null + + private var title: String? = null + private var message: String? = null + + override val layoutRes = R.layout.dialog_test + + override fun parseArguments(args: Bundle) { + title = arguments.getString(KEY_TITLE) + message = arguments.getString(KEY_MESSAGE) + } + + override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + uiTitle!!.text = title ?: "" + uiMessage!!.text = message ?: "" + } + + companion object { + + private val KEY_TITLE = "dialogTitle" + private val KEY_MESSAGE = "dialogMessage" + + fun show(title: String?, message: String?, fm: FragmentManager) { + + val dialog = TestDialog().apply { + arguments = Bundle().apply { + putString(KEY_TITLE, title ?: "") + putString(KEY_MESSAGE, message ?: "") + } + } + + dialog.show(fm, TestDialog::class.java.name) + } + } +} diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/utils/Keyboard.kt b/kotlin-base/app/src/main/java/com/flatstack/android/utils/Keyboard.kt new file mode 100644 index 0000000..8a3f927 --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/utils/Keyboard.kt @@ -0,0 +1,36 @@ +package com.flatstack.android.utils + +import android.app.Activity +import android.content.Context +import android.view.View +import android.view.inputmethod.InputMethodManager + +object Keyboard { + + fun hide(activity: Activity) { + val inputManager = activity + .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + val v = activity.currentFocus + inputManager.hideSoftInputFromWindow(v?.windowToken, 0) + } + + fun hide(view: View) { + val imm = view.context + .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + if (imm.isActive) { + imm.hideSoftInputFromWindow(view.windowToken, 0) + } + } + + fun show(context: Context) { + val imm = context + .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0) + } + + fun show(view: View) { + val inputManager = view.context + .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT) + } +} diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/utils/recycler_view/BaseAdapter.kt b/kotlin-base/app/src/main/java/com/flatstack/android/utils/recycler_view/BaseAdapter.kt new file mode 100644 index 0000000..b58df39 --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/utils/recycler_view/BaseAdapter.kt @@ -0,0 +1,38 @@ +package com.flatstack.android.utils.recycler_view + +import android.support.v7.widget.RecyclerView +import android.view.ViewGroup + +import rx.functions.Func1 + +/** + * Created by ereminilya on 14/12/16. + */ +class BaseAdapter> @JvmOverloads +constructor(private val items: MutableList, + private val func0: Func1, + private val onItemClickListener: OnItemClickListener? = null) + : RecyclerView.Adapter() { + + override fun onCreateViewHolder(viewGroup: ViewGroup, holderType: Int): VH { + val holder = func0.call(viewGroup) + holder.itemView.setOnClickListener { v -> + val position = holder.adapterPosition + if (position != RecyclerView.NO_POSITION && onItemClickListener != null) { + onItemClickListener.onItemClick(data[position]) + } + } + return holder + } + + override fun onBindViewHolder(vh: VH, position: Int) = vh.bind(items[position]) + + override fun getItemCount() = items.size + + val data: List get() = items + + fun add(item: T) { + this.items.add(item) + notifyItemInserted(items.size - 1) + } +} \ No newline at end of file diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/utils/recycler_view/BaseHolder.kt b/kotlin-base/app/src/main/java/com/flatstack/android/utils/recycler_view/BaseHolder.kt new file mode 100644 index 0000000..fb7bc1d --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/utils/recycler_view/BaseHolder.kt @@ -0,0 +1,12 @@ +package com.flatstack.android.utils.recycler_view + +import android.support.v7.widget.RecyclerView +import android.view.View + +/** + * Created by ereminilya on 14/12/16. + */ +abstract class BaseHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + + abstract fun bind(item: T) +} \ No newline at end of file diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/utils/recycler_view/OnItemClickListener.kt b/kotlin-base/app/src/main/java/com/flatstack/android/utils/recycler_view/OnItemClickListener.kt new file mode 100644 index 0000000..fe4120a --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/utils/recycler_view/OnItemClickListener.kt @@ -0,0 +1,9 @@ +package com.flatstack.android.utils.recycler_view + +/** + * Created by ereminilya on 14/12/16. + */ +interface OnItemClickListener { + + fun onItemClick(item: T) +} diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/utils/storage/IStorage.kt b/kotlin-base/app/src/main/java/com/flatstack/android/utils/storage/IStorage.kt new file mode 100644 index 0000000..8864e86 --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/utils/storage/IStorage.kt @@ -0,0 +1,36 @@ +package com.flatstack.android.utils.storage + +import java.lang.reflect.Type + +/** + * Created by ereminilya on 8/1/17. + */ + +interface IStorage { + + operator fun get(key: String, type: Type): T? + + fun put(key: String, item: T) + + fun putString(key: String, str: String) + + fun getString(key: String): String? + + fun putLong(key: String, number: Long) + + fun getLong(key: String, defaultValue: Long): Long + + fun putInt(key: String, number: Int) + + fun getInt(key: String, defaultValue: Int): Int + + fun putBoolean(key: String, value: Boolean) + + fun getBoolean(key: String, defaultValue: Boolean): Boolean + + fun remove(key: String) + + fun putCollection(key: String, items: List) + + fun getCollection(key: String, type: Type): List? +} diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/utils/storage/Storage.kt b/kotlin-base/app/src/main/java/com/flatstack/android/utils/storage/Storage.kt new file mode 100644 index 0000000..7ee2556 --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/utils/storage/Storage.kt @@ -0,0 +1,67 @@ +package com.flatstack.android.utils.storage + +import android.content.SharedPreferences + +import com.google.gson.Gson + +import java.lang.reflect.Type + +/** + * Created by ereminilya on 8/1/17. + */ + +class Storage(private val sp: SharedPreferences, private val gson: Gson) : IStorage { + + override fun get(key: String, type: Type): T? { + val json = sp.getString(key, "") + return if("" == json) null else gson.fromJson(json, type) + } + + override fun put(key: String, item: T) { + sp.edit().putString(key, gson.toJson(item)).apply() + } + + override fun putString(key: String, str: String) { + sp.edit().putString(key, str).apply() + } + + override fun getString(key: String): String? { + return sp.getString(key, null) + } + + override fun putLong(key: String, number: Long) { + sp.edit().putLong(key, number).apply() + } + + override fun getLong(key: String, defaultValue: Long): Long { + return sp.getLong(key, defaultValue) + } + + override fun putInt(key: String, number: Int) { + sp.edit().putInt(key, number).apply() + } + + override fun getInt(key: String, defaultValue: Int): Int { + return sp.getInt(key, defaultValue) + } + + override fun putBoolean(key: String, value: Boolean) { + sp.edit().putBoolean(key, value).apply() + } + + override fun getBoolean(key: String, defaultValue: Boolean): Boolean { + return sp.getBoolean(key, defaultValue) + } + + override fun remove(key: String) { + sp.edit().remove(key).apply() + } + + override fun putCollection(key: String, items: List) { + put(key, items) + } + + override fun getCollection(key: String, type: Type): List? { + return get>(key, type) + } +} \ No newline at end of file diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/BaseActivity.kt b/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/BaseActivity.kt new file mode 100644 index 0000000..8772394 --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/BaseActivity.kt @@ -0,0 +1,72 @@ +package com.flatstack.android.utils.ui + +import android.content.Context +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.support.v7.widget.Toolbar +import android.view.Menu +import android.view.MenuItem +import android.view.View +import butterknife.Bind +import butterknife.ButterKnife +import com.flatstack.android.R +import com.flatstack.android.utils.Keyboard + +abstract class BaseActivity : AppCompatActivity() { + + @Bind(R.id.toolbar) @JvmField var toolbar: View? = null + + abstract val uiInfo: UiInfo + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(uiInfo.layoutRes) + ButterKnife.bind(this) + if (intent != null && intent.extras != null) { + parseArguments(intent.extras) + } + if (toolbar != null) { + setSupportActionBar(toolbar as Toolbar?) + if (uiInfo.titleRes != 0) { + setTitle(uiInfo.titleRes) + } else if (uiInfo.titleStr != null) { + title = uiInfo.titleStr + } + if (uiInfo.hasBackButton) { + supportActionBar!!.setDisplayHomeAsUpEnabled(true) + } + } + if (savedInstanceState != null) { + restoreState(savedInstanceState) + } + } + + override fun setContentView(layoutResID: Int) { + super.setContentView(layoutResID) + ButterKnife.bind(this) + } + + protected fun restoreState(savedState: Bundle) {} + + protected fun parseArguments(extras: Bundle) {} + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + if (uiInfo.menuRes != 0) { + val inflater = menuInflater + inflater.inflate(uiInfo.menuRes, menu) + return true + } + return super.onCreateOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home && uiInfo.hasBackButton) { + Keyboard.hide(this) + finish() + return true + } + return super.onOptionsItemSelected(item) + } + + fun context(): Context = this +} diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/BaseDialogFragment.kt b/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/BaseDialogFragment.kt new file mode 100644 index 0000000..3a5915f --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/BaseDialogFragment.kt @@ -0,0 +1,74 @@ +package com.flatstack.android.utils.ui + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import android.support.annotation.LayoutRes +import android.support.v4.app.DialogFragment +import android.support.v4.app.FragmentActivity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.Window +import butterknife.ButterKnife + +abstract class BaseDialogFragment : DialogFragment() { + + @get:LayoutRes abstract val layoutRes: Int + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (arguments != null) { + parseArguments(arguments) + } + if (savedInstanceState != null) { + restoreState(savedInstanceState) + } + } + + protected fun restoreState(savedState: Bundle) {} + + protected open fun parseArguments(args: Bundle) { + throw IllegalStateException("should be overridden") + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val dialog = super.onCreateDialog(savedInstanceState) + dialog.window.requestFeature(Window.FEATURE_NO_TITLE) + return dialog + } + + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?): View? { + val v = inflater.inflate(layoutRes, container, false) + ButterKnife.bind(this, v) + return v + } + + override fun onDestroyView() { + ButterKnife.unbind(this) + super.onDestroyView() + } + + fun activity(): FragmentActivity = activity + + fun context(): Context = activity() + + companion object { + + protected fun show(dialogFragment: T, + activity: FragmentActivity): T { + val ft = activity.supportFragmentManager.beginTransaction() + val prev = activity.supportFragmentManager + .findFragmentByTag(dialogFragment.javaClass.name) + if (prev != null) { + ft.remove(prev) + (prev as DialogFragment).dismissAllowingStateLoss() + } + ft.addToBackStack(null) + dialogFragment.show(ft, dialogFragment.javaClass.name) + return dialogFragment + } + } +} \ No newline at end of file diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/BaseFragment.kt b/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/BaseFragment.kt new file mode 100644 index 0000000..9e4db23 --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/BaseFragment.kt @@ -0,0 +1,31 @@ +package com.flatstack.android.utils.ui + +import android.os.Bundle +import android.support.annotation.LayoutRes +import android.support.v4.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import butterknife.ButterKnife + +abstract class BaseFragment : Fragment() { + + @get:LayoutRes abstract val layoutRes: Int + + override fun onCreate(savedState: Bundle?) { + super.onCreate(savedState) + if (savedState != null) { + restoreState(savedState) + } + } + + fun restoreState(savedState: Bundle) {} + + override fun onCreateView(inflater: LayoutInflater?, + container: ViewGroup?, + savedInstanceState: Bundle?): View? { + val rootView = inflater!!.inflate(layoutRes, container, false) + ButterKnife.bind(this, rootView) + return rootView + } +} diff --git a/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/UiInfo.kt b/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/UiInfo.kt new file mode 100644 index 0000000..aa13dc7 --- /dev/null +++ b/kotlin-base/app/src/main/java/com/flatstack/android/utils/ui/UiInfo.kt @@ -0,0 +1,9 @@ +package com.flatstack.android.utils.ui + +import android.support.annotation.LayoutRes +import android.support.annotation.MenuRes +import android.support.annotation.StringRes + +class UiInfo(@param:LayoutRes val layoutRes: Int, @param:StringRes val titleRes: Int = 0, + @param:MenuRes val menuRes: Int = 0, val titleStr: String? = null, + val hasBackButton: Boolean = false) diff --git a/kotlin-base/app/src/main/res/drawable-hdpi/ic_launcher.png b/kotlin-base/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..a6ed594 Binary files /dev/null and b/kotlin-base/app/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/kotlin-base/app/src/main/res/drawable-mdpi/ic_launcher.png b/kotlin-base/app/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..0c5fd33 Binary files /dev/null and b/kotlin-base/app/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/kotlin-base/app/src/main/res/drawable-xhdpi/ic_launcher.png b/kotlin-base/app/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..a62b567 Binary files /dev/null and b/kotlin-base/app/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/kotlin-base/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/kotlin-base/app/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..fffa6a6 Binary files /dev/null and b/kotlin-base/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/kotlin-base/app/src/main/res/drawable-xxxhdpi/ic_launcher.png b/kotlin-base/app/src/main/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..2a27316 Binary files /dev/null and b/kotlin-base/app/src/main/res/drawable-xxxhdpi/ic_launcher.png differ diff --git a/kotlin-base/app/src/main/res/layout/activity_main.xml b/kotlin-base/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..788acd1 --- /dev/null +++ b/kotlin-base/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/kotlin-base/app/src/main/res/layout/dialog_test.xml b/kotlin-base/app/src/main/res/layout/dialog_test.xml new file mode 100644 index 0000000..81ff62d --- /dev/null +++ b/kotlin-base/app/src/main/res/layout/dialog_test.xml @@ -0,0 +1,32 @@ + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-base/app/src/main/res/layout/fragment_main.xml b/kotlin-base/app/src/main/res/layout/fragment_main.xml new file mode 100644 index 0000000..5196178 --- /dev/null +++ b/kotlin-base/app/src/main/res/layout/fragment_main.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/kotlin-base/app/src/main/res/values/dimens.xml b/kotlin-base/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..f11f745 --- /dev/null +++ b/kotlin-base/app/src/main/res/values/dimens.xml @@ -0,0 +1,3 @@ + + + diff --git a/kotlin-base/app/src/main/res/values/strings.xml b/kotlin-base/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..c677d36 --- /dev/null +++ b/kotlin-base/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Kotlin Ilya Base + diff --git a/kotlin-base/app/src/main/res/values/styles.xml b/kotlin-base/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..8542005 --- /dev/null +++ b/kotlin-base/app/src/main/res/values/styles.xml @@ -0,0 +1,2 @@ + + diff --git a/kotlin-base/app/src/main/res/values/themes.xml b/kotlin-base/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..a582f33 --- /dev/null +++ b/kotlin-base/app/src/main/res/values/themes.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/kotlin-base/app/src/main/res/values/tokens.xml b/kotlin-base/app/src/main/res/values/tokens.xml new file mode 100644 index 0000000..55344e5 --- /dev/null +++ b/kotlin-base/app/src/main/res/values/tokens.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/kotlin-base/app/src/test/java/com/flatstack/android/utils/storage/RuntimeStorage.java b/kotlin-base/app/src/test/java/com/flatstack/android/utils/storage/RuntimeStorage.java new file mode 100644 index 0000000..1c7faae --- /dev/null +++ b/kotlin-base/app/src/test/java/com/flatstack/android/utils/storage/RuntimeStorage.java @@ -0,0 +1,71 @@ +package com.flatstack.android.utils.storage; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class RuntimeStorage implements IStorage { + + private Map map = new HashMap<>(); + + @Override public void put(@NonNull String key, @NonNull T items) { + map.put(key, items); + } + + @Nullable @Override + public T get(@NonNull String key, @NonNull Type clazz) { + return (T) map.get(key); + } + + @Override public void putLong(@NonNull String key, long number) { + map.put(key, Long.valueOf(number)); + } + + @Override public long getLong(@NonNull String key, long defaultValue) { + Object o = map.get(key); + return o != null ? (long) o : defaultValue; + } + + @Override public void putInt(@NonNull String key, int number) { + map.put(key, Integer.valueOf(number)); + } + + @Override public int getInt(@NonNull String key, int defaultValue) { + Object o = map.get(key); + return o != null ? (int) o : defaultValue; + } + + @Override public void putBoolean(@NonNull String key, boolean value) { + map.put(key, Boolean.valueOf(value)); + } + + @Override public boolean getBoolean(@NonNull String key, boolean defaultValue) { + Object o = map.get(key); + return o != null ? (boolean) o : defaultValue; + } + + @Override public void putString(@NonNull String key, @NonNull String str) { + map.put(key, str); + } + + @Override public String getString(@NonNull String key) { + Object o = map.get(key); + return (o != null) ? (String) o : null; + } + + @Override public void remove(@NonNull String key) { + map.remove(key); + } + + @Override public void putCollection(@NonNull String key, @NonNull List items) { + map.put(key, items); + } + + @Override public List getCollection(@NonNull String key, @NonNull Type type) { + return (List) map.get(key); + } +} \ No newline at end of file diff --git a/kotlin-base/build.gradle b/kotlin-base/build.gradle new file mode 100644 index 0000000..b745fe0 --- /dev/null +++ b/kotlin-base/build.gradle @@ -0,0 +1,21 @@ +buildscript { + ext.kotlin_version = '1.1.2-4' + repositories { + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.0.0-alpha1' + classpath('com.stanfy.spoon:spoon-gradle-plugin:1.2.2') { + exclude module: 'guava' + } + classpath 'com.google.guava:guava:17.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + jcenter() + } +} \ No newline at end of file diff --git a/kotlin-base/circle.yml b/kotlin-base/circle.yml new file mode 100644 index 0000000..d6fdce2 --- /dev/null +++ b/kotlin-base/circle.yml @@ -0,0 +1,53 @@ +machine: + java: + version: oraclejdk8 + environment: + TERM: "dumb" + ADB_INSTALL_TIMEOUT: 5000 + GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' + +general: + artifacts: + - "/home/ubuntu/android-base/app/build/reports" + - "/home/ubuntu/android-base/app/build/spoon" + +dependencies: + pre: + - chmod +x app/set_animation_permissions.sh + - echo y | android update sdk --no-ui --all --filter "tools,platform-tools,android-25,extra-google-m2repository" + - echo y | android update sdk --no-ui --all --filter "build-tools-25.0.1" + - echo y | android update sdk --no-ui --all --filter "extra-android-m2repository" + + post: + # Create the android emulator + - echo n | android create avd -n test_android_17 -f -t android-17 + # [HINT] Circle-CI already have built-in emulator (circleci-android22), but it's so heavy. + # Make a SD Card image file for the android emulator + - mksdcard -l e 128M sdcard.img + +test: + pre: + - emulator -avd test_android_17 -no-audio -no-boot-anim -no-window -sdcard sdcard.img: + background: true + parallel: true + override: + - ./gradlew checkstyle lintProductionRelease testProductionReleaseUnitTest + - circle-android wait-for-boot + - sleep 20 + - adb shell input keyevent 82 + - adb shell settings put global window_animation_scale 0.0
 + - adb shell settings put global transition_animation_scale 0.0 + - adb shell settings put global animator_duration_scale 0.0 + - ./gradlew spoonProductionDebugAndroidTest + +#deployment: +# production: # just a label; label names are completely up to you +# branch: master +# commands: +# - ./gradlew publishApkRelease +# -Dorg.gradle.project.track=production +# beta: +# branch: develop +# commands: +# - ./gradlew publishApkRelease +# -Dorg.gradle.project.track=beta diff --git a/kotlin-base/deps.gradle b/kotlin-base/deps.gradle new file mode 100644 index 0000000..a1d8f62 --- /dev/null +++ b/kotlin-base/deps.gradle @@ -0,0 +1,52 @@ +ext { + versions = [ + okHttp : '3.3.1', + support : '25.1.0', + retrofit : '2.0.2', + espressoVersion : '2.2.2', + BUILD_TOOLS_VERSION: '25.0.1', + MIN_SDK_VERSION : 14, + TARGET_SDK_VERSION : 25 + ] + supportDeps = [ + appcompatV7 : "com.android.support:appcompat-v7:$versions.support", + recyclerView: "com.android.support:recyclerview-v7:$versions.support", + design : "com.android.support:design:$versions.support" +// gridLayout : "com.android.support:gridlayout-v7:$versions.support" +// cardView : "com.android.support:cardview-v7:$versions.support" +// palette : "com.android.support:palette-v7:$versions.support" + ] + rxJava = [ + rxJava : 'io.reactivex:rxjava:1.1.6', + rxAndroid: 'io.reactivex:rxandroid:1.2.1' + ] + retrofit = [ + retrofit : "com.squareup.retrofit2:retrofit:$versions.retrofit", + rxAdapter : "com.squareup.retrofit2:adapter-rxjava:$versions.retrofit", + gsonConverter: "com.squareup.retrofit2:converter-gson:$versions.retrofit" + ] + okHttp = [ + logger: "com.squareup.okhttp3:logging-interceptor:$versions.okHttp", + self : "com.squareup.okhttp3:okhttp:$versions.okHttp" + ] + unitTests = [ + supportAnnotation: "com.android.support:support-annotations:$versions.support", + junit : 'junit:junit:4.12', + assertj : 'com.squareup.assertj:assertj-android:1.0.0' + ] + androidTests = [ + espressoCore : "com.android.support.test.espresso:espresso-core:$versions.espressoVersion", + espressoContrib: "com.android.support.test.espresso:espresso-contrib:$versions.espressoVersion", + espressoIntents: "com.android.support.test.espresso:espresso-intents:$versions.espressoVersion", + testRunner : "com.android.support.test:runner:0.5", + testRules : "com.android.support.test:rules:0.5", + spoon : 'com.squareup.spoon:spoon-client:1.6.4' + ] + + supportLibs = supportDeps.values() + retrofitLibs = retrofit.values() + okHttpLibs = okHttp.values() + rxJavaLibs = rxJava.values() + unitTestLibs = unitTests.values() + androidTestsLibs = androidTests.values() + supportLibs +} \ No newline at end of file diff --git a/kotlin-base/gradle/wrapper/gradle-wrapper.jar b/kotlin-base/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..3c7abdf Binary files /dev/null and b/kotlin-base/gradle/wrapper/gradle-wrapper.jar differ diff --git a/kotlin-base/gradle/wrapper/gradle-wrapper.properties b/kotlin-base/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..0a54e9b --- /dev/null +++ b/kotlin-base/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun May 21 22:45:49 MSK 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-milestone-1-all.zip diff --git a/kotlin-base/gradlew b/kotlin-base/gradlew new file mode 100755 index 0000000..91a7e26 --- /dev/null +++ b/kotlin-base/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# 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" + which java >/dev/null 2>&1 || 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 + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/kotlin-base/gradlew.bat b/kotlin-base/gradlew.bat new file mode 100644 index 0000000..aec9973 --- /dev/null +++ b/kotlin-base/gradlew.bat @@ -0,0 +1,90 @@ +@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 + +@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= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="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! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/kotlin-base/keystore.properties b/kotlin-base/keystore.properties new file mode 100644 index 0000000..3eb1f61 --- /dev/null +++ b/kotlin-base/keystore.properties @@ -0,0 +1,4 @@ +#DO NOT FORGET EXCLUDE THIS FILE FROM REPO +storePassword=your_password +keyAlias=your_alias +keyPassword=your_key_password \ No newline at end of file diff --git a/kotlin-base/proguard.cfg b/kotlin-base/proguard.cfg new file mode 100644 index 0000000..58899e0 --- /dev/null +++ b/kotlin-base/proguard.cfg @@ -0,0 +1,12 @@ +# Dagger +-dontwarn dagger.internal.codegen.** +-keepclassmembers,allowobfuscation class * { + @javax.inject.* *; + @dagger.* *; + (); +} +-keep class dagger.* { *; } +-keep class javax.inject.* { *; } +-keep class * extends dagger.internal.Binding +-keep class * extends dagger.internal.ModuleAdapter +-keep class * extends dagger.internal.StaticInjection \ No newline at end of file diff --git a/kotlin-base/settings.gradle b/kotlin-base/settings.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/kotlin-base/settings.gradle @@ -0,0 +1 @@ +include ':app'