diff --git a/.travis.yml b/.travis.yml index 6d25e64..84a6e1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,13 +21,13 @@ before_script: - cp gradle.properties.ci.example gradle.properties # Emulator Management: Create, Start and Wait - echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a - - emulator -avd test -no-skin -no-audio -no-window & + - emulator -avd test -no-audio -no-window & - android-wait-for-emulator - adb shell input keyevent 82 & script: - - ./gradlew clean connectedAndroidTest --info - - ./gradlew testDebugUnitTest --info + - ./gradlew clean connectedAndroidTest + - ./gradlew testDebugUnitTest before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock diff --git a/README.md b/README.md index 0a29f57..42e891a 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,16 @@ # Android micropost app -This repository is an example Android application, which is based on Rails tutorial app. +This repository is an example Android application based on Rails tutorial app. [![Build Status](https://travis-ci.org/springboot-angular2-tutorial/android-app.svg?branch=master)](https://travis-ci.org/springboot-angular2-tutorial/android-app) -[![Coverage Status](https://coveralls.io/repos/github/springboot-angular2-tutorial/android-app/badge.svg?branch=master)](https://coveralls.io/github/springboot-angular2-tutorial/android-app?branch=master) -Key components. - -* Dagger 2 -* Retrolambda -* RxJava / RxAndroid -* Retrofit 2 -* Data Binding -* Robolectric 3 +* Kotlin 100% without kapt +* [Kodein](https://github.com/SalomonBrys/Kodein) as Dependency Injection +* [RxJava](https://github.com/ReactiveX/RxJava) / [RxAndroid](https://github.com/ReactiveX/RxAndroid) +* [RxBinding](https://github.com/JakeWharton/RxBinding) +* [Retrofit](https://github.com/square/retrofit) +* [Robolectric](http://robolectric.org/) for testing model layer +* [Espresso](https://google.github.io/android-testing-support-library/docs/espresso/) for testing presentation layer ## Getting Started @@ -40,7 +38,8 @@ Then, just run from Android Studio. Testing. ``` -./gradlew testDebug +./gradlew testDebugUnitTest +./gradlew connectedAndroidTest ``` Release build. diff --git a/app/build.gradle b/app/build.gradle index c762b48..9ecd999 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,7 +12,7 @@ android { targetSdkVersion 25 versionCode 1 versionName "1.0.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "com.hana053.micropost.testing.AppTestRunner" multiDexEnabled = true buildConfigField('String', 'API_URL', getProperty("micropost.apiUrl")) } @@ -44,9 +44,6 @@ android { androidTest.java.srcDirs += 'src/androidTest/kotlin' androidTest.java.srcDirs += 'src/testShared/kotlin' } - dexOptions { - javaMaxHeapSize '2g' - } configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1' } @@ -69,11 +66,11 @@ dependencies { compile "com.squareup.retrofit2:retrofit:$retrofit_version" compile "com.squareup.retrofit2:adapter-rxjava:$retrofit_version" compile "com.squareup.retrofit2:converter-moshi:$retrofit_version" - compile 'com.squareup.okhttp3:okhttp:3.6.0' - compile 'com.squareup.picasso:picasso:2.5.2' - compile 'com.jakewharton.timber:timber:4.3.1' - compile 'com.github.curioustechizen.android-ago:library:1.3.2' - compile group: 'com.nimbusds', name: 'nimbus-jose-jwt', version: '4.34' + compile "com.squareup.okhttp3:okhttp:$okhttp_version" + compile "com.squareup.picasso:picasso:$picasso_version" + compile "com.jakewharton.timber:timber:$timber_version" + compile "com.github.curioustechizen.android-ago:library:$android_ago_version" + compile "com.nimbusds:nimbus-jose-jwt:$jose_jwt_version" debugCompile "com.squareup.leakcanary:leakcanary-android:$leakcanary_version" @@ -84,6 +81,7 @@ dependencies { testCompile "org.robolectric:robolectric:$robolectric_version" testCompile "org.robolectric:shadows-support-v4:$robolectric_version" testCompile "com.squareup.leakcanary:leakcanary-android-no-op:$leakcanary_version" + testCompile group: 'org.assertj', name: 'assertj-core', version: assertj_version androidTestCompile "com.android.support.test:runner:$android_support_test_version" androidTestCompile "com.android.support.test:rules:$android_support_test_version" @@ -93,8 +91,10 @@ dependencies { androidTestCompile "com.android.support:support-annotations:$android_support_version" androidTestCompile "org.mockito:mockito-core:$mockito_version" androidTestCompile "com.nhaarman:mockito-kotlin:$mockito_kotlin_version" - androidTestCompile 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0' + androidTestCompile "com.linkedin.dexmaker:dexmaker-mockito:$dexmaker_mockito_version" androidTestCompile "com.squareup.leakcanary:leakcanary-android-no-op:$leakcanary_version" + androidTestCompile "com.linkedin.testbutler:test-butler-library:$testbutler_version" + androidTestCompile "com.squareup.assertj:assertj-android:$assertj_android_version" } repositories { mavenCentral() diff --git a/app/jacoco.gradle b/app/jacoco.gradle deleted file mode 100644 index 2e22f2b..0000000 --- a/app/jacoco.gradle +++ /dev/null @@ -1,47 +0,0 @@ -apply plugin: 'jacoco' - -jacoco { - // https://bintray.com/bintray/jcenter/org.jacoco:org.jacoco.core - toolVersion = "0.7.7.201606060606" -} - -android { - testOptions { - unitTests.all { - jacoco { - includeNoLocationClasses = true - } - } - } -} - -project.afterEvaluate { - - android.applicationVariants.all { variant -> - def name = variant.name - def testTaskName = "test${name.capitalize()}UnitTest" - - tasks.create(name: "${testTaskName}Coverage", type: JacocoReport, dependsOn: "$testTaskName") { - group = "Reporting" - description = "Generate Jacoco coverage reports for the ${name.capitalize()} build." - - classDirectories = fileTree( - dir: "${project.buildDir}/intermediates/classes/${name}", - excludes: ['**/R.class', - '**/R$*.class', - '**/*$ViewInjector*.*', - '**/*$ViewBinder*.*', - '**/BuildConfig.*', - '**/Manifest*.*'] - ) - - sourceDirectories = files(['src/main/java'].plus(android.sourceSets[name].java.srcDirs)) - executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec") - - reports { - xml.enabled = true - html.enabled = true - } - } - } -} \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/hana053/micropost/pages/login/LoginActivityTest.kt b/app/src/androidTest/kotlin/com/hana053/micropost/pages/login/LoginActivityTest.kt index 01ea514..9c28d8e 100644 --- a/app/src/androidTest/kotlin/com/hana053/micropost/pages/login/LoginActivityTest.kt +++ b/app/src/androidTest/kotlin/com/hana053/micropost/pages/login/LoginActivityTest.kt @@ -35,9 +35,9 @@ class LoginActivityTest : InjectableTest by InjectableTestImpl() { @Rule @JvmField val activityRule = ActivityTestRule(LoginActivity::class.java, false, false) - val loginBtn: Matcher = withId(R.id.loginBtn) - val emailEditText: Matcher = withId(R.id.emailEditText) - val passwordEditText: Matcher = withId(R.id.passwordEditText) + val loginBtn: Matcher = withId(R.id.btn_login) + val emailEditText: Matcher = withId(R.id.et_email) + val passwordEditText: Matcher = withId(R.id.et_password) @Test fun shouldBeOpened() { diff --git a/app/src/androidTest/kotlin/com/hana053/micropost/pages/main/MainActivityTest.kt b/app/src/androidTest/kotlin/com/hana053/micropost/pages/main/MainActivityTest.kt index 5bd731b..040db9b 100644 --- a/app/src/androidTest/kotlin/com/hana053/micropost/pages/main/MainActivityTest.kt +++ b/app/src/androidTest/kotlin/com/hana053/micropost/pages/main/MainActivityTest.kt @@ -70,8 +70,8 @@ class MainActivityTest : InjectableTest by InjectableTestImpl() { activityRule.launchActivity(null) - onView(withId(R.id.postRecyclerView)) - .check(matches(atPositionOnView(0, withText("my test content"), R.id.content))) + onView(withId(R.id.list_post)) + .check(matches(atPositionOnView(0, withText("my test content"), R.id.tv_post_content))) } @Test @@ -91,12 +91,12 @@ class MainActivityTest : InjectableTest by InjectableTestImpl() { } activityRule.launchActivity(null) - onView(withId(R.id.swipeRefreshLayout)).perform(swipeDown()) + onView(withId(R.id.swipe_refresh)).perform(swipeDown()) - onView(withId(R.id.postRecyclerView)) - .check(matches(atPositionOnView(0, withText("my new content"), R.id.content))) - onView(withId(R.id.postRecyclerView)) - .check(matches(atPositionOnView(1, withText("my test content"), R.id.content))) + onView(withId(R.id.list_post)) + .check(matches(atPositionOnView(0, withText("my new content"), R.id.tv_post_content))) + onView(withId(R.id.list_post)) + .check(matches(atPositionOnView(1, withText("my test content"), R.id.tv_post_content))) } @Test @@ -117,10 +117,10 @@ class MainActivityTest : InjectableTest by InjectableTestImpl() { activityRule.launchActivity(null) - onView(withId(R.id.postRecyclerView)) - .check(matches(atPositionOnView(0, withText("my test content"), R.id.content))) - onView(withId(R.id.postRecyclerView)) - .check(matches(atPositionOnView(1, withText("my old content"), R.id.content))) + onView(withId(R.id.list_post)) + .check(matches(atPositionOnView(0, withText("my test content"), R.id.tv_post_content))) + onView(withId(R.id.list_post)) + .check(matches(atPositionOnView(1, withText("my old content"), R.id.tv_post_content))) } @Test @@ -139,7 +139,7 @@ class MainActivityTest : InjectableTest by InjectableTestImpl() { } activityRule.launchActivity(null) - onView(withId(R.id.avatar)).perform(click()) + onView(withId(R.id.img_avatar)).perform(click()) verify(navigator).navigateToUserShow(1) } @@ -158,7 +158,7 @@ class MainActivityTest : InjectableTest by InjectableTestImpl() { } activityRule.launchActivity(null) - onView(withId(R.id.newMicropostBtn)).perform(click()) + onView(withId(R.id.btn_new_micropost)).perform(click()) verify(navigator).navigateToMicropostNew() } @@ -180,9 +180,9 @@ class MainActivityTest : InjectableTest by InjectableTestImpl() { activityRule.launchActivity(null) verify(feedInteractor, times(1)).loadNextFeed(null) - onView(withId(R.id.newMicropostBtn)).perform(click()) - onView(withId(R.id.postEditText)).perform(typeText("hello")) - onView(withId(R.id.postBtn)).perform(closeSoftKeyboard(), click()) + onView(withId(R.id.btn_new_micropost)).perform(click()) + onView(withId(R.id.et_post)).perform(typeText("hello")) + onView(withId(R.id.btn_post)).perform(closeSoftKeyboard(), click()) verify(feedInteractor, times(2)).loadNextFeed(null) } diff --git a/app/src/androidTest/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewActivityTest.kt b/app/src/androidTest/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewActivityTest.kt index ab4cbaf..3201976 100644 --- a/app/src/androidTest/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewActivityTest.kt +++ b/app/src/androidTest/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewActivityTest.kt @@ -1,5 +1,6 @@ package com.hana053.micropost.pages.micropostnew +import org.assertj.android.api.Assertions.assertThat import android.support.test.espresso.Espresso.onView import android.support.test.espresso.action.ViewActions.* import android.support.test.espresso.assertion.ViewAssertions.matches @@ -20,7 +21,6 @@ import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.verify -import org.hamcrest.CoreMatchers.`is` import org.hamcrest.CoreMatchers.not import org.junit.Rule import org.junit.Test @@ -57,10 +57,10 @@ class MicropostNewActivityTest : InjectableTest by InjectableTestImpl() { overrideAppBindings { fakeAuthToken() } activityRule.launchActivity(null) - onView(withId(R.id.postBtn)).check(matches(not(isEnabled()))) + onView(withId(R.id.btn_post)).check(matches(not(isEnabled()))) - onView(withId(R.id.postEditText)).perform(typeText("a")) - onView(withId(R.id.postBtn)).check(matches(isEnabled())) + onView(withId(R.id.et_post)).perform(typeText("a")) + onView(withId(R.id.btn_post)).check(matches(isEnabled())) } @Test @@ -74,11 +74,11 @@ class MicropostNewActivityTest : InjectableTest by InjectableTestImpl() { } activityRule.launchActivity(null) - onView(withId(R.id.postEditText)).perform(typeText("a")) - onView(withId(R.id.postBtn)).perform(closeSoftKeyboard(), click()) + onView(withId(R.id.et_post)).perform(typeText("a")) + onView(withId(R.id.btn_post)).perform(closeSoftKeyboard(), click()) verify(micropostInteractor).create(MicropostInteractor.MicropostRequest("a")) - assertThat(activityRule.activity.isFinishing, `is`(true)) + assertThat(activityRule.activity).isFinishing } } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListActivityTest.kt b/app/src/androidTest/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListActivityTest.kt index 53efc87..a15a6cb 100644 --- a/app/src/androidTest/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListActivityTest.kt +++ b/app/src/androidTest/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListActivityTest.kt @@ -22,7 +22,6 @@ import com.nhaarman.mockito_kotlin.anyOrNull import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.verify -import org.hamcrest.CoreMatchers.allOf import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -48,10 +47,7 @@ class RelatedUserListActivityTest : InjectableTest by InjectableTestImpl() { }) } launchActivity(FOLLOWER, 1) - onView(allOf( - isDescendantOfA(withResourceName("android:id/action_bar_container")), - withText(R.string.Followers) - )) + onView(withText(R.string.Followers)).check(matches(isDisplayed())) } @Test @@ -78,8 +74,8 @@ class RelatedUserListActivityTest : InjectableTest by InjectableTestImpl() { } launchActivity(FOLLOWER, 1) - onView(withId(R.id.userRecyclerView)) - .check(matches(atPositionOnView(0, withText("John Doe"), R.id.userName))) + onView(withId(R.id.list_user)) + .check(matches(atPositionOnView(0, withText("John Doe"), R.id.tv_user_name))) } @Test @@ -99,10 +95,10 @@ class RelatedUserListActivityTest : InjectableTest by InjectableTestImpl() { } launchActivity(FOLLOWER, 1) - onView(withId(R.id.userRecyclerView)) - .check(matches(atPositionOnView(0, withText("John Doe"), R.id.userName))) - onView(withId(R.id.userRecyclerView)) - .check(matches(atPositionOnView(1, withText("Old Follower"), R.id.userName))) + onView(withId(R.id.list_user)) + .check(matches(atPositionOnView(0, withText("John Doe"), R.id.tv_user_name))) + onView(withId(R.id.list_user)) + .check(matches(atPositionOnView(1, withText("Old Follower"), R.id.tv_user_name))) } @Test @@ -126,8 +122,8 @@ class RelatedUserListActivityTest : InjectableTest by InjectableTestImpl() { } launchActivity(FOLLOWER, 1) - onView(withId(R.id.followBtn)).perform(click()) - onView(withId(R.id.followBtn)).check(matches(withText(R.string.Unfollow))) + onView(withId(R.id.btn_follow)).perform(click()) + onView(withId(R.id.btn_follow)).check(matches(withText(R.string.Unfollow))) } @Test @@ -145,7 +141,7 @@ class RelatedUserListActivityTest : InjectableTest by InjectableTestImpl() { bind(overrides = true) with instance(navigator) } launchActivity(FOLLOWER, 1) - onView(withId(R.id.avatar)).perform(click()) + onView(withId(R.id.img_avatar)).perform(click()) verify(navigator).navigateToUserShow(100) } @@ -162,10 +158,7 @@ class RelatedUserListActivityTest : InjectableTest by InjectableTestImpl() { }) } launchActivity(FOLLOWING, 1) - onView(allOf( - isDescendantOfA(withResourceName("android:id/action_bar_container")), - withText(R.string.Followings) - )) + onView(withText(R.string.Followings)).check(matches(isDisplayed())) } @Test @@ -182,8 +175,8 @@ class RelatedUserListActivityTest : InjectableTest by InjectableTestImpl() { } launchActivity(FOLLOWING, 1) - onView(withId(R.id.userRecyclerView)) - .check(matches(atPositionOnView(0, withText("John Doe"), R.id.userName))) + onView(withId(R.id.list_user)) + .check(matches(atPositionOnView(0, withText("John Doe"), R.id.tv_user_name))) } private fun launchActivity(listType: RelatedUserListActivity.ListType, userId: Long) { diff --git a/app/src/androidTest/kotlin/com/hana053/micropost/pages/signup/SignupActivityTest.kt b/app/src/androidTest/kotlin/com/hana053/micropost/pages/signup/SignupActivityTest.kt index 965a20a..d4fc763 100644 --- a/app/src/androidTest/kotlin/com/hana053/micropost/pages/signup/SignupActivityTest.kt +++ b/app/src/androidTest/kotlin/com/hana053/micropost/pages/signup/SignupActivityTest.kt @@ -7,6 +7,7 @@ import android.support.test.espresso.matcher.ViewMatchers.* import android.support.test.filters.LargeTest import android.support.test.rule.ActivityTestRule import android.support.test.runner.AndroidJUnit4 +import android.view.View import com.github.salomonbrys.kodein.bind import com.github.salomonbrys.kodein.instance import com.hana053.micropost.R @@ -24,13 +25,15 @@ import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.verify import kotlinx.android.synthetic.main.fragment_signup_email.* import kotlinx.android.synthetic.main.fragment_signup_full_name.* -import org.hamcrest.CoreMatchers.`is` +import org.assertj.android.api.Assertions.assertThat +import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.not +import org.hamcrest.Matcher import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import retrofit2.HttpException import retrofit2.Response -import retrofit2.adapter.rxjava.HttpException import rx.Observable @@ -41,6 +44,19 @@ class SignupActivityTest : InjectableTest by InjectableTestImpl() { @Rule @JvmField val activityRule = ActivityTestRule(SignupActivity::class.java, false, false) + val fullNameNextBtn: Matcher = allOf( + withId(R.id.btn_next), + isDescendantOfA(withId(R.id.fragment_signup_full_name)) + ) + val emailNextBtn: Matcher = allOf( + withId(R.id.btn_next), + isDescendantOfA(withId(R.id.fragment_signup_email)) + ) + val passwordNextBtn: Matcher = allOf( + withId(R.id.btn_next), + isDescendantOfA(withId(R.id.fragment_signup_password)) + ) + @Test fun shouldBeOpened() { activityRule.launchActivity(null) @@ -51,18 +67,18 @@ class SignupActivityTest : InjectableTest by InjectableTestImpl() { fun shouldInputName() { activityRule.launchActivity(null) - onView(withId(R.id.fullNameNextBtn)).check(matches(not(isEnabled()))) - onView(withId(R.id.fullNameInvalid)).check(matches(not(isDisplayed()))) + onView(fullNameNextBtn).check(matches(not(isEnabled()))) + onView(withId(R.id.tv_full_name_invalid)).check(matches(not(isDisplayed()))) - onView(withId(R.id.fullName)).perform(typeText("a"), closeSoftKeyboard()) - onView(withId(R.id.fullNameInvalid)).check(matches(isDisplayed())) - onView(withId(R.id.fullNameNextBtn)).check(matches(not(isEnabled()))) + onView(withId(R.id.et_full_name)).perform(typeText("a"), closeSoftKeyboard()) + onView(withId(R.id.tv_full_name_invalid)).check(matches(isDisplayed())) + onView(fullNameNextBtn).check(matches(not(isEnabled()))) - onView(withId(R.id.fullName)).perform(replaceText("John Doe"), closeSoftKeyboard()) - onView(withId(R.id.fullNameNextBtn)).check(matches(isEnabled())) - onView(withId(R.id.fullNameInvalid)).check(matches(not(isDisplayed()))) + onView(withId(R.id.et_full_name)).perform(replaceText("John Doe"), closeSoftKeyboard()) + onView(fullNameNextBtn).check(matches(isEnabled())) + onView(withId(R.id.tv_full_name_invalid)).check(matches(not(isDisplayed()))) - onView(withId(R.id.fullNameNextBtn)).perform(click()) + onView(fullNameNextBtn).perform(click()) onView(withText(R.string.what_s_your_email)).check(matches(isDisplayed())) } @@ -72,18 +88,18 @@ class SignupActivityTest : InjectableTest by InjectableTestImpl() { moveToEmailWithName("John Doe") - onView(withId(R.id.emailNextBtn)).check(matches(not(isEnabled()))) - onView(withId(R.id.emailInvalid)).check(matches(not(isDisplayed()))) + onView(emailNextBtn).check(matches(not(isEnabled()))) + onView(withId(R.id.tv_email_invalid)).check(matches(not(isDisplayed()))) - onView(withId(R.id.email)).perform(typeText("a"), closeSoftKeyboard()) - onView(withId(R.id.emailInvalid)).check(matches(isDisplayed())) - onView(withId(R.id.emailNextBtn)).check(matches(not(isEnabled()))) + onView(withId(R.id.et_email)).perform(typeText("a"), closeSoftKeyboard()) + onView(withId(R.id.tv_email_invalid)).check(matches(isDisplayed())) + onView(emailNextBtn).check(matches(not(isEnabled()))) - onView(withId(R.id.email)).perform(replaceText("test@test.com"), closeSoftKeyboard()) - onView(withId(R.id.emailNextBtn)).check(matches(isEnabled())) - onView(withId(R.id.emailInvalid)).check(matches(not(isDisplayed()))) + onView(withId(R.id.et_email)).perform(replaceText("test@test.com"), closeSoftKeyboard()) + onView(emailNextBtn).check(matches(isEnabled())) + onView(withId(R.id.tv_email_invalid)).check(matches(not(isDisplayed()))) - onView(withId(R.id.emailNextBtn)).perform(click()) + onView(emailNextBtn).perform(click()) onView(withText(R.string.you_ll_need_a_password)).check(matches(isDisplayed())) } @@ -104,18 +120,18 @@ class SignupActivityTest : InjectableTest by InjectableTestImpl() { moveToEmailWithName("John Doe") moveToPasswordWithEmail("test@test.com") - onView(withId(R.id.passwordNextBtn)).check(matches(not(isEnabled()))) - onView(withId(R.id.passwordInvalid)).check(matches(not(isDisplayed()))) + onView(passwordNextBtn).check(matches(not(isEnabled()))) + onView(withId(R.id.tv_password_invalid)).check(matches(not(isDisplayed()))) - onView(withId(R.id.password)).perform(typeText("a"), closeSoftKeyboard()) - onView(withId(R.id.passwordInvalid)).check(matches(isDisplayed())) - onView(withId(R.id.passwordNextBtn)).check(matches(not(isEnabled()))) + onView(withId(R.id.et_password)).perform(typeText("a"), closeSoftKeyboard()) + onView(withId(R.id.tv_password_invalid)).check(matches(isDisplayed())) + onView(passwordNextBtn).check(matches(not(isEnabled()))) - onView(withId(R.id.password)).perform(replaceText("secret123"), closeSoftKeyboard()) - onView(withId(R.id.passwordNextBtn)).check(matches(isEnabled())) - onView(withId(R.id.passwordInvalid)).check(matches(not(isDisplayed()))) + onView(withId(R.id.et_password)).perform(replaceText("secret123"), closeSoftKeyboard()) + onView(passwordNextBtn).check(matches(isEnabled())) + onView(withId(R.id.tv_password_invalid)).check(matches(not(isDisplayed()))) - onView(withId(R.id.passwordNextBtn)).perform(click()) + onView(passwordNextBtn).perform(click()) verify(navigator).navigateToMain() } @@ -147,26 +163,26 @@ class SignupActivityTest : InjectableTest by InjectableTestImpl() { onView(withId(android.R.id.content)).perform(pressBack()) onView(withText(R.string.what_s_your_email)).check(matches(isDisplayed())) - assertThat(activity.email.text.toString(), `is`("test@test.com")) + assertThat(activity.et_email).hasTextString("test@test.com") onView(withId(android.R.id.content)).perform(pressBack()) onView(withText(R.string.hi_what_s_your_name)).check(matches(isDisplayed())) - assertThat(activity.fullName.text.toString(), `is`("John Doe")) + assertThat(activity.et_full_name).hasTextString("John Doe") } private fun moveToEmailWithName(name: String) { - onView(withId(R.id.fullName)).perform(typeText(name), closeSoftKeyboard()) - onView(withId(R.id.fullNameNextBtn)).perform(click()) + onView(withId(R.id.et_full_name)).perform(typeText(name), closeSoftKeyboard()) + onView(fullNameNextBtn).perform(click()) } private fun moveToPasswordWithEmail(email: String) { - onView(withId(R.id.email)).perform(typeText(email), closeSoftKeyboard()) - onView(withId(R.id.emailNextBtn)).perform(click()) + onView(withId(R.id.et_email)).perform(typeText(email), closeSoftKeyboard()) + onView(emailNextBtn).perform(click()) } private fun moveToMainWithPassword(password: String) { - onView(withId(R.id.password)).perform(typeText(password), closeSoftKeyboard()) - onView(withId(R.id.passwordNextBtn)).perform(click()) + onView(withId(R.id.et_password)).perform(typeText(password), closeSoftKeyboard()) + onView(passwordNextBtn).perform(click()) } } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/hana053/micropost/pages/top/TopActivityTest.kt b/app/src/androidTest/kotlin/com/hana053/micropost/pages/top/TopActivityTest.kt index 80cb03b..1ee4c3e 100644 --- a/app/src/androidTest/kotlin/com/hana053/micropost/pages/top/TopActivityTest.kt +++ b/app/src/androidTest/kotlin/com/hana053/micropost/pages/top/TopActivityTest.kt @@ -42,7 +42,7 @@ class TopActivityTest : InjectableTest by InjectableTestImpl() { } activityRule.launchActivity(null) - onView(withId(R.id.signupBtn)).perform(click()) + onView(withId(R.id.btn_signup)).perform(click()) verify(navigator).navigateToSignup() } @@ -55,7 +55,7 @@ class TopActivityTest : InjectableTest by InjectableTestImpl() { } activityRule.launchActivity(null) - onView(withId(R.id.loginBtn)).perform(click()) + onView(withId(R.id.btn_login)).perform(click()) verify(navigator).navigateToLogin() } diff --git a/app/src/androidTest/kotlin/com/hana053/micropost/pages/usershow/UserShowActivityTest.kt b/app/src/androidTest/kotlin/com/hana053/micropost/pages/usershow/UserShowActivityTest.kt index d98c015..7d9acde 100644 --- a/app/src/androidTest/kotlin/com/hana053/micropost/pages/usershow/UserShowActivityTest.kt +++ b/app/src/androidTest/kotlin/com/hana053/micropost/pages/usershow/UserShowActivityTest.kt @@ -4,7 +4,8 @@ import android.content.Intent import android.support.test.espresso.Espresso.onView import android.support.test.espresso.action.ViewActions.click import android.support.test.espresso.assertion.ViewAssertions.matches -import android.support.test.espresso.matcher.ViewMatchers.* +import android.support.test.espresso.matcher.ViewMatchers.withId +import android.support.test.espresso.matcher.ViewMatchers.withText import android.support.test.filters.LargeTest import android.support.test.rule.ActivityTestRule import android.support.test.runner.AndroidJUnit4 @@ -41,8 +42,6 @@ class UserShowActivityTest : InjectableTest by InjectableTestImpl() { fakeLoadingDetail() } launchActivityWithUserId(1) - onView(withText(R.string.followers)).check(matches(isDisplayed())) - onView(withText(R.string.followings)).check(matches(isDisplayed())) } @Test @@ -67,7 +66,7 @@ class UserShowActivityTest : InjectableTest by InjectableTestImpl() { }) } launchActivityWithUserId(1) - onView(withText("John Doe")).check(matches(isDisplayed())) + onView(withId(R.id.tv_user_name)).check(matches(withText("John Doe"))) } @Test @@ -91,14 +90,14 @@ class UserShowActivityTest : InjectableTest by InjectableTestImpl() { } launchActivityWithUserId(1) - onView(withId(R.id.followBtn)).check(matches(withText(R.string.Follow))) + onView(withId(R.id.btn_follow)).check(matches(withText(R.string.Follow))) // Do Follow. It will finally fetch user again. `when`(userInteractor.get(1)).thenReturn(Observable.just( TestUser.copy(name = "John Doe", isFollowedByMe = true) )) - onView(withId(R.id.followBtn)).perform(click()) - onView(withId(R.id.followBtn)).check(matches(withText(R.string.Unfollow))) + onView(withId(R.id.btn_follow)).perform(click()) + onView(withId(R.id.btn_follow)).check(matches(withText(R.string.Unfollow))) } @Test @@ -112,7 +111,7 @@ class UserShowActivityTest : InjectableTest by InjectableTestImpl() { } launchActivityWithUserId(1) - onView(withId(R.id.followers)).perform(click()) + onView(withId(R.id.tv_followers)).perform(click()) verify(navigator).navigateToFollowerList(1) } @@ -128,7 +127,7 @@ class UserShowActivityTest : InjectableTest by InjectableTestImpl() { } launchActivityWithUserId(1) - onView(withId(R.id.followings)).perform(click()) + onView(withId(R.id.tv_followings)).perform(click()) verify(navigator).navigateToFollowingList(1) } @@ -149,8 +148,8 @@ class UserShowActivityTest : InjectableTest by InjectableTestImpl() { launchActivityWithUserId(1) - onView(withId(R.id.postRecyclerView)) - .check(matches(atPositionOnView(0, withText("my test content"), R.id.content))) + onView(withId(R.id.list_post)) + .check(matches(atPositionOnView(0, withText("my test content"), R.id.tv_post_content))) } private fun launchActivityWithUserId(userId: Long) { @@ -159,7 +158,7 @@ class UserShowActivityTest : InjectableTest by InjectableTestImpl() { private fun Kodein.Builder.fakeLoadingDetail() { bind(overrides = true) with instance(mock { - on { get(any()) } doReturn Observable.empty() + on { get(any()) } doReturn Observable.just(TestUser) }) } diff --git a/app/src/androidTest/kotlin/com/hana053/micropost/testing/AppTestRunner.kt b/app/src/androidTest/kotlin/com/hana053/micropost/testing/AppTestRunner.kt new file mode 100644 index 0000000..1b1635c --- /dev/null +++ b/app/src/androidTest/kotlin/com/hana053/micropost/testing/AppTestRunner.kt @@ -0,0 +1,21 @@ +package com.hana053.micropost.testing + +import android.os.Bundle +import android.support.test.InstrumentationRegistry +import android.support.test.runner.AndroidJUnitRunner +import com.linkedin.android.testbutler.TestButler + + +class AppTestRunner : AndroidJUnitRunner() { + + override fun onStart() { + TestButler.setup(InstrumentationRegistry.getTargetContext()) + super.onStart() + } + + override fun finish(resultCode: Int, results: Bundle) { + TestButler.teardown(InstrumentationRegistry.getTargetContext()) + super.finish(resultCode, results) + } + +} \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/hana053/micropost/testing/EspressoHelpers.kt b/app/src/androidTest/kotlin/com/hana053/micropost/testing/EspressoHelpers.kt index 6cdb1e2..7943acd 100644 --- a/app/src/androidTest/kotlin/com/hana053/micropost/testing/EspressoHelpers.kt +++ b/app/src/androidTest/kotlin/com/hana053/micropost/testing/EspressoHelpers.kt @@ -13,11 +13,11 @@ fun atPositionOnView( targetId: Int ) = object : BoundedMatcher(RecyclerView::class.java) { - override fun matchesSafely(recyclerView: RecyclerView): Boolean { - val viewHolder = recyclerView.findViewHolderForAdapterPosition(position) - val targetView = viewHolder.itemView.findViewById(targetId) - return matcher.matches(targetView) - } + override fun matchesSafely(recyclerView: RecyclerView) = + recyclerView.findViewHolderForAdapterPosition(position) + .itemView + .findViewById(targetId) + .let { matcher.matches(it) } override fun describeTo(description: Description?) { description?.appendText("has view id $matcher at position $position") diff --git a/app/src/main/kotlin/com/hana053/micropost/BaseApplication.kt b/app/src/main/kotlin/com/hana053/micropost/BaseApplication.kt index 75ca77e..a34f674 100644 --- a/app/src/main/kotlin/com/hana053/micropost/BaseApplication.kt +++ b/app/src/main/kotlin/com/hana053/micropost/BaseApplication.kt @@ -49,8 +49,6 @@ abstract class BaseApplication : Application(), KodeinAware { Pair(RelatedUserListActivity::class.java, relatedUserListModule()) ) - fun getOverridingModule(clazz: Class<*>): Kodein.Module { - return overridingModules[clazz]!! - } + fun getOverridingModule(clazz: Class<*>) = overridingModules[clazz]!! } diff --git a/app/src/main/kotlin/com/hana053/micropost/Extensions.kt b/app/src/main/kotlin/com/hana053/micropost/Extensions.kt index 2b588fb..6b5de5d 100644 --- a/app/src/main/kotlin/com/hana053/micropost/Extensions.kt +++ b/app/src/main/kotlin/com/hana053/micropost/Extensions.kt @@ -1,9 +1,6 @@ package com.hana053.micropost import android.app.Activity -import com.github.salomonbrys.kodein.Kodein - -fun Activity.getOverridingModule(clazz: Class<*>): Kodein.Module { - return (application as BaseApplication).getOverridingModule(clazz) -} +fun Activity.getOverridingModule() = + (application as BaseApplication).getOverridingModule(javaClass) diff --git a/app/src/main/kotlin/com/hana053/micropost/domain/Avatar.kt b/app/src/main/kotlin/com/hana053/micropost/domain/Avatar.kt index db9b681..5409fd5 100644 --- a/app/src/main/kotlin/com/hana053/micropost/domain/Avatar.kt +++ b/app/src/main/kotlin/com/hana053/micropost/domain/Avatar.kt @@ -4,7 +4,5 @@ package com.hana053.micropost.domain interface Avatar { val avatarHash: String - fun avatarUrl(size: Int = 72): String { - return "https://secure.gravatar.com/avatar/$avatarHash?s=$size" - } + fun avatarUrl(size: Int = 72) = "https://secure.gravatar.com/avatar/$avatarHash?s=$size" } diff --git a/app/src/main/kotlin/com/hana053/micropost/domain/RelatedUser.kt b/app/src/main/kotlin/com/hana053/micropost/domain/RelatedUser.kt index b9d741f..a0057b0 100644 --- a/app/src/main/kotlin/com/hana053/micropost/domain/RelatedUser.kt +++ b/app/src/main/kotlin/com/hana053/micropost/domain/RelatedUser.kt @@ -10,7 +10,7 @@ data class RelatedUser( val userStats: UserStats, val relationshipId: Long ) : Avatar { - fun toUser(): User { - return User(id, name, email, avatarHash, isFollowedByMe, userStats) - } + + fun toUser() = User(id, name, email, avatarHash, isFollowedByMe, userStats) + } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/domain/User.kt b/app/src/main/kotlin/com/hana053/micropost/domain/User.kt index d19e7f0..3b37b74 100644 --- a/app/src/main/kotlin/com/hana053/micropost/domain/User.kt +++ b/app/src/main/kotlin/com/hana053/micropost/domain/User.kt @@ -5,7 +5,6 @@ data class User( val name: String, val email: String?, override val avatarHash: String, - val isFollowedByMe: Boolean, + val isFollowedByMe: Boolean? = null, val userStats: UserStats ) : Avatar - diff --git a/app/src/main/kotlin/com/hana053/micropost/interactor/InteractorModule.kt b/app/src/main/kotlin/com/hana053/micropost/interactor/InteractorModule.kt index 88f5769..6cd73e9 100644 --- a/app/src/main/kotlin/com/hana053/micropost/interactor/InteractorModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/interactor/InteractorModule.kt @@ -17,19 +17,16 @@ fun interactorModule() = Kodein.Module { bind() with singleton { val authTokenRepository = instance() - OkHttpClient().newBuilder() - .addInterceptor { chain -> - val authToken = authTokenRepository.get() - val original = chain.request() - val builder = original.newBuilder() - if (authToken != null) - builder.header("authorization", "Bearer " + authToken) - val request = builder - .method(original.method(), original.body()) - .build() - chain.proceed(request) - } - .build() + OkHttpClient().newBuilder().addInterceptor { chain -> + val original = chain.request() + val modified = original.newBuilder().apply { + authTokenRepository.get()?.let { + header("authorization", "Bearer $it") + } + }.method(original.method(), original.body()).build() + + chain.proceed(modified) + }.build() } bind() with singleton { @@ -44,39 +41,33 @@ fun interactorModule() = Kodein.Module { } bind() with singleton { - val retrofit = instance() - retrofit.create(LoginInteractor::class.java) + instance().create() } bind() with singleton { - val retrofit = instance() - retrofit.create(FeedInteractor::class.java) + instance().create() } bind() with singleton { - val retrofit = instance() - retrofit.create(UserInteractor::class.java) + instance().create() } bind() with singleton { - val retrofit = instance() - retrofit.create(RelationshipInteractor::class.java) + instance().create() } bind() with singleton { - val retrofit = instance() - retrofit.create(UserMicropostInteractor::class.java) + instance().create() } bind() with singleton { - val retrofit = instance() - retrofit.create(MicropostInteractor::class.java) + instance().create() } bind() with singleton { - val retrofit = instance() - retrofit.create(RelatedUserListInteractor::class.java) + instance().create() } - } +inline fun Retrofit.create(): T = create(T::class.java) + diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/Presenter.kt b/app/src/main/kotlin/com/hana053/micropost/pages/Presenter.kt index ed76425..586d223 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/Presenter.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/Presenter.kt @@ -15,21 +15,19 @@ interface Presenter { fun bind() fun Observable.withProgressDialog(): Observable = Observable.using({ - val progressBar = ProgressBar(view.content.context, null, android.R.attr.progressBarStyle) - progressBar.isIndeterminate = true - progressBar.visibility = View.VISIBLE - - val rl = RelativeLayout(view.content.context) - rl.gravity = Gravity.CENTER - rl.addView(progressBar) - + val progressBar = ProgressBar(view.content.context, null, android.R.attr.progressBarStyle).apply { + isIndeterminate = true + visibility = View.VISIBLE + } + val rl = RelativeLayout(view.content.context).apply { + gravity = Gravity.CENTER + addView(progressBar) + } val layoutParams = RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT ) - view.content.addView(rl, layoutParams) - progressBar }, { this }, { it.visibility = View.GONE diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/ViewWrapper.kt b/app/src/main/kotlin/com/hana053/micropost/pages/ViewWrapper.kt index 33e4151..db1d08d 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/ViewWrapper.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/ViewWrapper.kt @@ -1,8 +1,11 @@ package com.hana053.micropost.pages +import android.content.Context import android.view.ViewGroup interface ViewWrapper { val content: ViewGroup + + fun context(): Context = content.context } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginActivity.kt b/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginActivity.kt index 583946e..2482d98 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginActivity.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginActivity.kt @@ -27,7 +27,6 @@ class LoginActivity : RxAppCompatActivity(), AppCompatActivityInjector { destroyInjector() } - override fun provideOverridingModule() - = getOverridingModule(LoginActivity::class.java) + override fun provideOverridingModule() = getOverridingModule() } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginModule.kt index f46f088..521013c 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginModule.kt @@ -15,8 +15,7 @@ fun loginModule() = Kodein.Module { } bind() with autoScopedSingleton(androidActivityScope) { - val content = instance().activity_login - LoginView(content) + instance().activity_login.let(::LoginView) } } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginPresenter.kt b/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginPresenter.kt index dadc621..c880d5b 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginPresenter.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginPresenter.kt @@ -15,26 +15,28 @@ class LoginPresenter( val emailChanges = view.emailChanges.share() val passwordChanges = view.passwordChanges.share() - val credentials = Observable.combineLatest(emailChanges, passwordChanges, { email, password -> - Triple(email, password, email.isNotBlank() && password.isNotBlank()) - }) + val emailAndPassword = Observable.combineLatest(emailChanges, passwordChanges, ::EmailAndPassword) - credentials + emailAndPassword .bindToLifecycle() - .map { it.third } + .map { it.isValid() } .subscribe { view.loginEnabled.call(it) } view.loginClicks .bindToLifecycle() - .withLatestFrom(credentials, { click, credentials -> - credentials.first to credentials.second + .withLatestFrom(emailAndPassword, { click, emailAndPassword -> + emailAndPassword }) .flatMap { - loginService.login(it.first, it.second) + loginService.login(it.email, it.password) .withProgressDialog() } .subscribe { navigator.navigateToMain() } } + data class EmailAndPassword(val email: String, val password: String) { + fun isValid() = email.isNotBlank() && password.isNotBlank() + } + } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginView.kt b/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginView.kt index 57230a7..cc16558 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/login/LoginView.kt @@ -6,14 +6,19 @@ import com.jakewharton.rxbinding.view.clicks import com.jakewharton.rxbinding.view.enabled import com.jakewharton.rxbinding.widget.textChanges import kotlinx.android.synthetic.main.activity_login.view.* +import rx.Observable class LoginView(override val content: ViewGroup) : ViewWrapper { // Events - val emailChanges = content.emailEditText.textChanges().map { it.toString() }!! - val passwordChanges = content.passwordEditText.textChanges().map { it.toString() }!! - val loginClicks = content.loginBtn.clicks() + val emailChanges: Observable = content.et_email + .textChanges() + .map { it.toString() } + val passwordChanges: Observable = content.et_password + .textChanges() + .map { it.toString() } + val loginClicks = content.btn_login.clicks() // Props - val loginEnabled = content.loginBtn.enabled() + val loginEnabled = content.btn_login.enabled() } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/main/MainActivity.kt b/app/src/main/kotlin/com/hana053/micropost/pages/main/MainActivity.kt index fa60332..c97e31d 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/main/MainActivity.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/main/MainActivity.kt @@ -62,7 +62,6 @@ class MainActivity : RxAppCompatActivity(), AppCompatActivityInjector { return super.onOptionsItemSelected(item) } - override fun provideOverridingModule() - = getOverridingModule(MainActivity::class.java) + override fun provideOverridingModule() = getOverridingModule() } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/main/MainModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/main/MainModule.kt index 6b74867..d8966c6 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/main/MainModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/main/MainModule.kt @@ -20,8 +20,8 @@ fun mainModule() = Kodein.Module { } bind() with autoScopedSingleton(androidActivityScope) { - val content = instance().activity_main - MainView(content, instance()) + instance().activity_main + .let { MainView(it, instance()) } } bind() with autoScopedSingleton(androidActivityScope) { diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/main/MainPresenter.kt b/app/src/main/kotlin/com/hana053/micropost/pages/main/MainPresenter.kt index f9973ee..ac14320 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/main/MainPresenter.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/main/MainPresenter.kt @@ -26,7 +26,7 @@ class MainPresenter( .flatMap { mainService.loadNextFeed() } .subscribe { view.swipeRefreshing.call(false) } - view.scrolledToBottom + view.scrollsToBottom .bindToLifecycle() .flatMap { mainService.loadPrevFeed() diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/main/MainView.kt b/app/src/main/kotlin/com/hana053/micropost/pages/main/MainView.kt index e0f1495..509faff 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/main/MainView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/main/MainView.kt @@ -17,23 +17,21 @@ class MainView( postListAdapter: PostListAdapter ) : ViewWrapper { - private val postRecyclerView = content.postRecyclerView - private val swipeRefreshLayout = content.swipeRefreshLayout + private val listPost = content.list_post + private val swipeRefresh = content.swipe_refresh // Events - val swipeRefreshes = swipeRefreshLayout.refreshes() - val scrolledToBottom: Observable = postRecyclerView - .scrollEvents() - .filter { !postRecyclerView.canScrollVertically(1) } - val newMicropostClicks = content.newMicropostBtn.clicks() + val swipeRefreshes = swipeRefresh.refreshes() + val scrollsToBottom: Observable = listPost.scrollEvents() + .filter { !listPost.canScrollVertically(1) } + val newMicropostClicks = content.btn_new_micropost.clicks() // Props - val swipeRefreshing = swipeRefreshLayout.refreshing() + val swipeRefreshing = swipeRefresh.refreshing() init { - val context = content.context - postRecyclerView.layoutManager = LinearLayoutManager(context) - postRecyclerView.adapter = postListAdapter + listPost.layoutManager = LinearLayoutManager(context()) + listPost.adapter = postListAdapter } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MIcropostNewModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MIcropostNewModule.kt index b90542f..457d11d 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MIcropostNewModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MIcropostNewModule.kt @@ -16,8 +16,7 @@ fun micropostNewModule() = Kodein.Module { } bind() with autoScopedSingleton(androidActivityScope) { - val content = instance().activity_micropost_new - MicropostNewView(content) + instance().activity_micropost_new.let(::MicropostNewView) } bind() with autoScopedSingleton(androidActivityScope) { diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewActivity.kt b/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewActivity.kt index 73e28d3..b8613eb 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewActivity.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewActivity.kt @@ -32,6 +32,5 @@ class MicropostNewActivity : RxAppCompatActivity(), AppCompatActivityInjector { destroyInjector() } - override fun provideOverridingModule() - = getOverridingModule(MicropostNewActivity::class.java) + override fun provideOverridingModule() = getOverridingModule() } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewView.kt b/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewView.kt index 7f31b55..915dadb 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/micropostnew/MicropostNewView.kt @@ -11,9 +11,9 @@ import kotlinx.android.synthetic.main.activity_micropost_new.view.* class MicropostNewView(override val content: ViewGroup) : ViewWrapper { // Events - val postTextChanges = content.postEditText.textChanges() - val postBtnClicks = content.postBtn.clicks() + val postTextChanges = content.et_post.textChanges() + val postBtnClicks = content.btn_post.clicks() // Props - val postBtnEnabled = content.postBtn.enabled() + val postBtnEnabled = content.btn_post.enabled() } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListActivity.kt b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListActivity.kt index 41dc0ae..302122a 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListActivity.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListActivity.kt @@ -57,7 +57,6 @@ class RelatedUserListActivity : RxAppCompatActivity(), AppCompatActivityInjector return super.onOptionsItemSelected(item) } - override fun provideOverridingModule() - = getOverridingModule(RelatedUserListActivity::class.java) + override fun provideOverridingModule() = getOverridingModule() } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListAdapter.kt b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListAdapter.kt index b2bdf41..73e9474 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListAdapter.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListAdapter.kt @@ -24,44 +24,42 @@ class RelatedUserListAdapter( val followBtnClicksSubject: PublishSubject = PublishSubject.create() val avatarClicksSubject: PublishSubject = PublishSubject.create() - override fun getItemCount(): Int { - return users.size + class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val container: LinearLayout = view.container + val avatar: ImageView = view.img_avatar + val userName: TextView = view.tv_user_name + val followBtn: Button = view.btn_follow } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val v = LayoutInflater.from(parent.context) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = + LayoutInflater.from(parent.context) .inflate(R.layout.item_related_users, parent, false) - return ViewHolder(v) - } + .let(::ViewHolder) override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = users[position] - holder.userName.text = item.name - holder.container.tag = item + holder.apply { + container.tag = item + userName.text = item.name - AvatarView(holder.avatar).render(item.toUser()) - holder.avatar.setOnClickListener { - avatarClicksSubject.onNext(item.toUser()) - } + AvatarView(avatar).render(item.toUser()) + avatar.setOnClickListener { + avatarClicksSubject.onNext(item.toUser()) + } - val followBtnView = FollowBtnView(holder.followBtn) - followBtnView.render(item.toUser()) - holder.followBtn.setOnClickListener { - followBtnClicksSubject.onNext(followBtnView) + FollowBtnView(followBtn).apply { + render(item.toUser()) + followBtn.setOnClickListener { + followBtnClicksSubject.onNext(this) + } + } } } - class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { - val container: LinearLayout = view.container - val avatar: ImageView = view.avatar - val userName: TextView = view.userName - val followBtn: Button = view.followBtn - } + override fun getItemCount() = users.size - fun getLastItemId(): Long? { - return users.map { it.relationshipId }.lastOrNull() - } + fun getLastItemId() = users.map { it.relationshipId }.lastOrNull() fun addAll(location: Int, users: List): Boolean { if (this.users.addAll(location, users)) { diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListModule.kt index 5726490..9d94d48 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListModule.kt @@ -1,8 +1,11 @@ package com.hana053.micropost.pages.relateduserlist import android.app.Activity -import com.github.salomonbrys.kodein.* +import com.github.salomonbrys.kodein.Kodein import com.github.salomonbrys.kodein.android.androidActivityScope +import com.github.salomonbrys.kodein.autoScopedSingleton +import com.github.salomonbrys.kodein.bind +import com.github.salomonbrys.kodein.instance import com.hana053.micropost.pages.relateduserlist.RelatedUserListActivity.Companion.KEY_LIST_TYPE import com.hana053.micropost.pages.relateduserlist.RelatedUserListActivity.Companion.KEY_USER_ID import com.hana053.micropost.pages.relateduserlist.RelatedUserListActivity.ListType.FOLLOWER @@ -20,8 +23,8 @@ fun relatedUserListModule() = Kodein.Module { } bind() with autoScopedSingleton(androidActivityScope) { - val content = instance().activity_related_user_list - RelatedUserListView(content, instance()) + instance().activity_related_user_list + .let { RelatedUserListView(it, instance()) } } bind() with autoScopedSingleton(androidActivityScope) { @@ -35,15 +38,17 @@ fun relatedUserListModule() = Kodein.Module { } } - bind(KEY_USER_ID) with provider { - instance().intent.extras.getLong(KEY_USER_ID) + bind(KEY_USER_ID) with autoScopedSingleton(androidActivityScope) { + extras().getLong(KEY_USER_ID) } - bind() with provider { - instance().intent.extras.getSerializable(KEY_LIST_TYPE) as RelatedUserListActivity.ListType + bind() with autoScopedSingleton(androidActivityScope) { + extras().getSerializable(KEY_LIST_TYPE) as RelatedUserListActivity.ListType } import(followBtnModule()) } +private fun Kodein.extras() = instance().intent.extras + diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListPresenter.kt b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListPresenter.kt index 1aeef8e..0f6de03 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListPresenter.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListPresenter.kt @@ -21,7 +21,7 @@ class RelatedUserListPresenter( .withProgressDialog() .subscribe() - view.scrolledToBottom + view.scrollsToBottom .bindToLifecycle() .flatMap { relatedUserListService.listUsers(userId) diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListView.kt b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListView.kt index e3c873c..b230108 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/RelatedUserListView.kt @@ -14,16 +14,15 @@ class RelatedUserListView( relatedUserListAdapter: RelatedUserListAdapter ) : ViewWrapper { - private val userRecyclerView = content.userRecyclerView + private val listUser = content.list_user // Events - val scrolledToBottom: Observable = userRecyclerView.scrollEvents() - .filter { !userRecyclerView.canScrollVertically(1) } + val scrollsToBottom: Observable = listUser.scrollEvents() + .filter { !listUser.canScrollVertically(1) } init { - val context = content.context - userRecyclerView.layoutManager = LinearLayoutManager(context) - userRecyclerView.adapter = relatedUserListAdapter + listUser.layoutManager = LinearLayoutManager(context()) + listUser.adapter = relatedUserListAdapter } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/followerlist/FollowerListService.kt b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/followerlist/FollowerListService.kt index e82810f..d9f93a4 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/followerlist/FollowerListService.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/followerlist/FollowerListService.kt @@ -19,11 +19,7 @@ class FollowerListService( context: Context ) : RelatedUserListService { - private val context: Context - - init { - this.context = context.applicationContext - } + private val context = context.applicationContext override fun listUsers(userId: Long): Observable> { val maxId = adapter.getLastItemId() @@ -37,7 +33,5 @@ class FollowerListService( .onErrorResumeNext { Observable.empty() } } - override fun title(): String { - return context.getString(R.string.Followers) - } + override fun title(): String = context.getString(R.string.Followers) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/followinglist/FollowingListService.kt b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/followinglist/FollowingListService.kt index 92f6a33..62af020 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/followinglist/FollowingListService.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/relateduserlist/followinglist/FollowingListService.kt @@ -19,11 +19,7 @@ class FollowingListService( context: Context ) : RelatedUserListService { - private val context: Context - - init { - this.context = context.applicationContext - } + private val context = context.applicationContext override fun listUsers(userId: Long): Observable> { val maxId = adapter.getLastItemId() @@ -37,7 +33,5 @@ class FollowingListService( .onErrorResumeNext { Observable.empty() } } - override fun title(): String { - return context.getString(R.string.Followings) - } + override fun title(): String = context.getString(R.string.Followings) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupActivity.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupActivity.kt index 92d9226..f0ee92e 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupActivity.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupActivity.kt @@ -39,7 +39,6 @@ class SignupActivity : RxAppCompatActivity(), AppCompatActivityInjector { signupNavigator.navigateToPrev() } - override fun provideOverridingModule() - = getOverridingModule(SignupActivity::class.java) + override fun provideOverridingModule() = getOverridingModule() } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupNavigatorImpl.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupNavigatorImpl.kt index d62c340..52c7112 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupNavigatorImpl.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupNavigatorImpl.kt @@ -27,12 +27,12 @@ class SignupNavigatorImpl( } override fun navigateToPrev() { - val backStackCnt = activity.supportFragmentManager.backStackEntryCount - if (backStackCnt == 0) { - activity.finish() - return + activity.supportFragmentManager.backStackEntryCount.let { + when (it) { + 0 -> activity.finish() + else -> activity.supportFragmentManager.popBackStack() + } } - activity.supportFragmentManager.popBackStack() } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupServiceImpl.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupServiceImpl.kt index e8c921d..2c2c795 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupServiceImpl.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupServiceImpl.kt @@ -5,7 +5,7 @@ import android.widget.Toast import com.hana053.micropost.interactor.UserInteractor import com.hana053.micropost.service.HttpErrorHandler import com.hana053.micropost.service.LoginService -import retrofit2.adapter.rxjava.HttpException +import retrofit2.HttpException import rx.Observable import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers @@ -21,26 +21,24 @@ class SignupServiceImpl( private val context = context.applicationContext - override fun signup(request: UserInteractor.SignupRequest): Observable { - return userInteractor.create(request) + override fun signup(request: UserInteractor.SignupRequest): Observable = + userInteractor.create(request) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) - .doOnError { err -> - if (isEmailAlreadyTaken(err)) { - Toast.makeText(context, "This email is already taken.", Toast.LENGTH_LONG).show() - signupNavigator.navigateToPrev() - } else { - httpErrorHandler.handleError(err) + .doOnError { + when { + isEmailAlreadyTaken(it) -> { + Toast.makeText(context, "This email is already taken.", Toast.LENGTH_LONG).show() + signupNavigator.navigateToPrev() + } + else -> httpErrorHandler.handleError(it) } } .onErrorResumeNext { Observable.empty() } .flatMap { loginService.login(request.email, request.password) } - } - private fun isEmailAlreadyTaken(e: Throwable): Boolean { - return e is HttpException && e.code() == 400 - } + private fun isEmailAlreadyTaken(e: Throwable) = e is HttpException && e.code() == 400 } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupState.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupState.kt index 18bf965..43f23ea 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupState.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/SignupState.kt @@ -8,7 +8,7 @@ data class SignupState( var email: String = "", var password: String = "" ) { - fun toSignupRequest(): UserInteractor.SignupRequest { - return UserInteractor.SignupRequest(fullName, email, password) - } + + fun toSignupRequest() = UserInteractor.SignupRequest(fullName, email, password) + } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailFragment.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailFragment.kt index 85922e4..16cfcd7 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailFragment.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailFragment.kt @@ -17,9 +17,8 @@ class SignupEmailFragment : RxFragment(), SupportFragmentInjector { private val presenter: SignupEmailPresenter by instance() - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_signup_email, container, false) - } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = + inflater.inflate(R.layout.fragment_signup_email, container, false) override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailPresenter.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailPresenter.kt index fe95a8d..cb8c009 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailPresenter.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailPresenter.kt @@ -33,9 +33,9 @@ class SignupEmailPresenter( } } - private fun isFormValid(email: CharSequence): Boolean { - val emailPattern = "^[^0-9][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*@\\[?([\\d\\w\\.-]+)]?$" - return email.matches(emailPattern.toRegex()) - } + private fun isFormValid(email: CharSequence) = + "^[^0-9][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*@\\[?([\\d\\w\\.-]+)]?$" + .let(String::toRegex) + .let { email.matches(it) } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailView.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailView.kt index c28b5ad..5a9b0d8 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupEmailView.kt @@ -12,11 +12,11 @@ import kotlinx.android.synthetic.main.fragment_signup_email.view.* class SignupEmailView(override val content: ViewGroup) : ViewWrapper { // Events - val emailChanges = content.email.textChanges() - val nextBtnClicks = content.emailNextBtn.clicks() + val emailChanges = content.et_email.textChanges() + val nextBtnClicks = content.btn_next.clicks() // Props - val nextBtnEnabled = content.emailNextBtn.enabled() - val emailInvalidVisibility = content.emailInvalid.visibility() + val nextBtnEnabled = content.btn_next.enabled() + val emailInvalidVisibility = content.tv_email_invalid.visibility() } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupFullNameModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupFullNameModule.kt index 931943d..3a0e289 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupFullNameModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/email/SignupFullNameModule.kt @@ -16,8 +16,7 @@ fun signupEmailModule() = Kodein.Module { } bind() with autoScopedSingleton(androidActivityScope) { - val content = instance().fragment_signup_email - SignupEmailView(content) + instance().fragment_signup_email.let(::SignupEmailView) } } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameFragment.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameFragment.kt index d3fc7b2..c4d03ef 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameFragment.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameFragment.kt @@ -17,9 +17,8 @@ class SignupFullNameFragment : RxFragment(), SupportFragmentInjector { private val presenter: SignupFullNamePresenter by instance() - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_signup_full_name, container, false) - } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = + inflater.inflate(R.layout.fragment_signup_full_name, container, false) override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameModule.kt index a28ab90..d52bc6d 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameModule.kt @@ -16,8 +16,7 @@ fun signupFullNameModule() = Kodein.Module { } bind() with autoScopedSingleton(androidActivityScope) { - val content = instance().fragment_signup_full_name - SignupFullNameView(content) + instance().fragment_signup_full_name.let(::SignupFullNameView) } } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNamePresenter.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNamePresenter.kt index bf01de0..3d6e615 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNamePresenter.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNamePresenter.kt @@ -33,8 +33,6 @@ class SignupFullNamePresenter( } } - private fun isFormValid(fullName: CharSequence): Boolean { - return fullName.length >= 4 - } + private fun isFormValid(fullName: CharSequence) = fullName.length >= 4 } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameView.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameView.kt index 58e660e..7e48508 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/fullname/SignupFullNameView.kt @@ -12,11 +12,11 @@ import kotlinx.android.synthetic.main.fragment_signup_full_name.view.* class SignupFullNameView(override val content: ViewGroup) : ViewWrapper { // Events - val fullNameChanges = content.fullName.textChanges() - val nextBtnClicks = content.fullNameNextBtn.clicks() + val fullNameChanges = content.et_full_name.textChanges() + val nextBtnClicks = content.btn_next.clicks() // Props - val nextBtnEnabled = content.fullNameNextBtn.enabled() - val fullNameInvalidVisibility = content.fullNameInvalid.visibility() + val nextBtnEnabled = content.btn_next.enabled() + val fullNameInvalidVisibility = content.tv_full_name_invalid.visibility() } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordFragment.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordFragment.kt index 6bf0ee3..85b1c15 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordFragment.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordFragment.kt @@ -17,9 +17,8 @@ class SignupPasswordFragment : RxFragment(), SupportFragmentInjector { private val presenter: SignupPasswordPresenter by instance() - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_signup_password, container, false) - } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = + inflater.inflate(R.layout.fragment_signup_password, container, false) override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordModule.kt index 4b03631..9e94b1b 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordModule.kt @@ -16,8 +16,7 @@ fun signupPasswordModule() = Kodein.Module { } bind() with autoScopedSingleton(androidActivityScope) { - val content = instance().fragment_signup_password - SignupPasswordView(content) + instance().fragment_signup_password.let(::SignupPasswordView) } } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordPresenter.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordPresenter.kt index fa97496..e86a4ec 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordPresenter.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordPresenter.kt @@ -41,8 +41,6 @@ class SignupPasswordPresenter( .subscribe { navigator.navigateToMain() } } - private fun isFormValid(password: CharSequence): Boolean { - return password.length >= 8 - } + private fun isFormValid(password: CharSequence): Boolean = password.length >= 8 } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordView.kt b/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordView.kt index ceb1b9c..a555424 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/signup/password/SignupPasswordView.kt @@ -12,10 +12,10 @@ import kotlinx.android.synthetic.main.fragment_signup_password.view.* class SignupPasswordView(override val content: ViewGroup) : ViewWrapper { // Events - val passwordChanges = content.password.textChanges() - val nextBtnClicks = content.passwordNextBtn.clicks() + val passwordChanges = content.et_password.textChanges() + val nextBtnClicks = content.btn_next.clicks() // Props - val nextBtnEnabled = content.passwordNextBtn.enabled() - val passwordInvalidVisibility = content.passwordInvalid.visibility() + val nextBtnEnabled = content.btn_next.enabled() + val passwordInvalidVisibility = content.tv_password_invalid.visibility() } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/top/TopActivity.kt b/app/src/main/kotlin/com/hana053/micropost/pages/top/TopActivity.kt index 6c4000c..aa0b0a8 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/top/TopActivity.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/top/TopActivity.kt @@ -28,8 +28,7 @@ class TopActivity : RxAppCompatActivity(), AppCompatActivityInjector { destroyInjector() } - override fun provideOverridingModule() - = getOverridingModule(TopActivity::class.java) + override fun provideOverridingModule() = getOverridingModule() } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/top/TopModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/top/TopModule.kt index c221cad..451cd0a 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/top/TopModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/top/TopModule.kt @@ -15,8 +15,7 @@ fun topModule() = Kodein.Module { } bind() with autoScopedSingleton(androidActivityScope) { - val content = instance().activity_top - TopView(content) + instance().activity_top.let(::TopView) } } diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/top/TopView.kt b/app/src/main/kotlin/com/hana053/micropost/pages/top/TopView.kt index 76594a9..cfbb5ad 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/top/TopView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/top/TopView.kt @@ -7,6 +7,6 @@ import kotlinx.android.synthetic.main.activity_top.view.* class TopView(override val content: ViewGroup) : ViewWrapper { - val signupClicks = content.signupBtn.clicks() - val loginClicks = content.loginBtn.clicks() + val signupClicks = content.btn_signup.clicks() + val loginClicks = content.btn_login.clicks() } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/UserShowActivity.kt b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/UserShowActivity.kt index 5524051..afe5a64 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/UserShowActivity.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/UserShowActivity.kt @@ -53,7 +53,6 @@ class UserShowActivity : RxAppCompatActivity(), AppCompatActivityInjector { return super.onOptionsItemSelected(item) } - override fun provideOverridingModule() - = getOverridingModule(UserShowActivity::class.java) + override fun provideOverridingModule() = getOverridingModule() } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/UserShowModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/UserShowModule.kt index baa7cb3..d9ab323 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/UserShowModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/UserShowModule.kt @@ -2,9 +2,10 @@ package com.hana053.micropost.pages.usershow import android.app.Activity import com.github.salomonbrys.kodein.Kodein +import com.github.salomonbrys.kodein.android.androidActivityScope +import com.github.salomonbrys.kodein.autoScopedSingleton import com.github.salomonbrys.kodein.bind import com.github.salomonbrys.kodein.instance -import com.github.salomonbrys.kodein.provider import com.hana053.micropost.pages.usershow.UserShowActivity.Companion.KEY_USER_ID import com.hana053.micropost.pages.usershow.detail.userShowDetailModule import com.hana053.micropost.pages.usershow.posts.userShowPostsModule @@ -12,7 +13,7 @@ import com.hana053.micropost.shared.followbtn.followBtnModule fun userShowModule() = Kodein.Module { - bind(KEY_USER_ID) with provider { + bind(KEY_USER_ID) with autoScopedSingleton(androidActivityScope) { instance().intent.extras.getLong(KEY_USER_ID) } @@ -22,4 +23,3 @@ fun userShowModule() = Kodein.Module { } - diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailModule.kt index 4ccf54d..30d7f7c 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailModule.kt @@ -16,8 +16,7 @@ fun userShowDetailModule() = Kodein.Module { } bind() with autoScopedSingleton(androidActivityScope) { - val content = instance()._user_detail - UserShowDetailView(content) + instance()._user_detail.let(::UserShowDetailView) } bind() with autoScopedSingleton(androidActivityScope) { diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailService.kt b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailService.kt index 3c89525..8e34ab7 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailService.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailService.kt @@ -13,12 +13,11 @@ class UserShowDetailService( private val httpErrorHandler: HttpErrorHandler ) { - fun getUser(userId: Long): Observable { - return userInteractor.get(userId) + fun getUser(userId: Long): Observable = + userInteractor.get(userId) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .doOnError { httpErrorHandler.handleError(it) } .onErrorResumeNext { Observable.empty() } - } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailView.kt b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailView.kt index cdbcb00..dd0fb43 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/detail/UserShowDetailView.kt @@ -2,6 +2,7 @@ package com.hana053.micropost.pages.usershow.detail import android.annotation.SuppressLint import android.view.ViewGroup +import com.hana053.micropost.R import com.hana053.micropost.domain.User import com.hana053.micropost.pages.ViewWrapper import com.hana053.micropost.shared.avatar.AvatarView @@ -13,15 +14,13 @@ class UserShowDetailView( override val content: ViewGroup ) : ViewWrapper { - private val userName = content.userName - private val followerCnt = content.followerCnt - private val followingCnt = content.followingCnt - private val followers = content.followers - private val followings = content.followings + private val userName = content.tv_user_name + private val followers = content.tv_followers + private val followings = content.tv_followings // Sub View - private val followBtnView = FollowBtnView(content.followBtn) - private val avatarView = AvatarView(content.avatar) + private val followBtnView = FollowBtnView(content.btn_follow) + private val avatarView = AvatarView(content.img_avatar) // Events val followersClicks = followers.clicks() @@ -33,8 +32,8 @@ class UserShowDetailView( followBtnView.render(user) avatarView.render(user) userName.text = user.name - followingCnt.text = "${user.userStats.followingCnt} " - followerCnt.text = "${user.userStats.followerCnt} " + followers.text = "${user.userStats.followerCnt} ${context().getString(R.string.followers)}" + followings.text = "${user.userStats.followingCnt} ${context().getString(R.string.followings)}" } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/posts/UserShowPostsModule.kt b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/posts/UserShowPostsModule.kt index 0ecc1f7..f0d74d8 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/posts/UserShowPostsModule.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/posts/UserShowPostsModule.kt @@ -21,8 +21,8 @@ fun userShowPostsModule() = Kodein.Module { } bind() with autoScopedSingleton(androidActivityScope) { - val content = instance()._user_posts - UserShowPostsView(content, instance()) + instance()._user_posts + .let { UserShowPostsView(it, instance()) } } bind() with autoScopedSingleton(androidActivityScope) { diff --git a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/posts/UserShowPostsView.kt b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/posts/UserShowPostsView.kt index ca4deb7..0ed32d2 100644 --- a/app/src/main/kotlin/com/hana053/micropost/pages/usershow/posts/UserShowPostsView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/pages/usershow/posts/UserShowPostsView.kt @@ -12,12 +12,13 @@ class UserShowPostsView( postListAdapter: PostListAdapter ) : ViewWrapper { - private val postRecyclerView = content.postRecyclerView + private val listPost = content.list_post init { - val context = content.context - postRecyclerView.layoutManager = LinearLayoutManager(context) - postRecyclerView.adapter = postListAdapter - postRecyclerView.isNestedScrollingEnabled = false + with(listPost) { + layoutManager = LinearLayoutManager(context()) + adapter = postListAdapter + isNestedScrollingEnabled = false + } } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/repository/AuthTokenRepositoryImpl.kt b/app/src/main/kotlin/com/hana053/micropost/repository/AuthTokenRepositoryImpl.kt index 5034246..bb5db7a 100644 --- a/app/src/main/kotlin/com/hana053/micropost/repository/AuthTokenRepositoryImpl.kt +++ b/app/src/main/kotlin/com/hana053/micropost/repository/AuthTokenRepositoryImpl.kt @@ -8,20 +8,17 @@ class AuthTokenRepositoryImpl( private val AUTH_TOKEN = "AUTH_TOKEN" - override fun get(): String? { - return sharedPreferences.getString(AUTH_TOKEN, null) - } + override fun get(): String? = + sharedPreferences.getString(AUTH_TOKEN, null) - override fun set(authToken: String) { + override fun set(authToken: String) = sharedPreferences.edit() .putString(AUTH_TOKEN, authToken) .apply() - } - override fun clear() { + override fun clear() = sharedPreferences.edit() .putString(AUTH_TOKEN, null) .apply() - } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/service/AuthServiceImpl.kt b/app/src/main/kotlin/com/hana053/micropost/service/AuthServiceImpl.kt index fe90f2a..8d112ad 100644 --- a/app/src/main/kotlin/com/hana053/micropost/service/AuthServiceImpl.kt +++ b/app/src/main/kotlin/com/hana053/micropost/service/AuthServiceImpl.kt @@ -3,8 +3,6 @@ package com.hana053.micropost.service import com.hana053.micropost.domain.User import com.hana053.micropost.repository.AuthTokenRepository import com.nimbusds.jose.JWSObject -import java.lang.Long -import java.text.ParseException class AuthServiceImpl( @@ -14,13 +12,11 @@ class AuthServiceImpl( override fun isMyself(user: User): Boolean { val authToken = authTokenRepository.get() ?: return false - try { - val jwsObject = JWSObject.parse(authToken) - val sub = jwsObject.payload.toJSONObject()["sub"].toString() - return user.id == Long.valueOf(sub) - } catch (e: ParseException) { - throw RuntimeException(e) - } + return user.id == JWSObject.parse(authToken) + .payload + .toJSONObject()["sub"] + .toString() + .toLong() } diff --git a/app/src/main/kotlin/com/hana053/micropost/service/HttpErrorHandler.java b/app/src/main/kotlin/com/hana053/micropost/service/HttpErrorHandler.java deleted file mode 100644 index c37d67a..0000000 --- a/app/src/main/kotlin/com/hana053/micropost/service/HttpErrorHandler.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.hana053.micropost.service; - -public interface HttpErrorHandler { - - void handleError(Throwable throwable); - -} diff --git a/app/src/main/kotlin/com/hana053/micropost/service/HttpErrorHandler.kt b/app/src/main/kotlin/com/hana053/micropost/service/HttpErrorHandler.kt new file mode 100644 index 0000000..715fd03 --- /dev/null +++ b/app/src/main/kotlin/com/hana053/micropost/service/HttpErrorHandler.kt @@ -0,0 +1,7 @@ +package com.hana053.micropost.service + +interface HttpErrorHandler { + + fun handleError(throwable: Throwable) + +} diff --git a/app/src/main/kotlin/com/hana053/micropost/service/HttpErrorHandlerImpl.kt b/app/src/main/kotlin/com/hana053/micropost/service/HttpErrorHandlerImpl.kt index 4a95357..461c3b9 100644 --- a/app/src/main/kotlin/com/hana053/micropost/service/HttpErrorHandlerImpl.kt +++ b/app/src/main/kotlin/com/hana053/micropost/service/HttpErrorHandlerImpl.kt @@ -2,7 +2,7 @@ package com.hana053.micropost.service import android.content.Context import android.widget.Toast -import retrofit2.adapter.rxjava.HttpException +import retrofit2.HttpException import timber.log.Timber import java.net.ConnectException import java.net.SocketTimeoutException @@ -15,23 +15,27 @@ internal class HttpErrorHandlerImpl( private val context: Context = context.applicationContext override fun handleError(throwable: Throwable) { - try { - throw throwable - } catch (e: SocketTimeoutException) { - Toast.makeText(context, "Connection timed out.", Toast.LENGTH_LONG).show() - } catch (e: ConnectException) { - Toast.makeText(context, "Cannot connect to server.", Toast.LENGTH_LONG).show() - } catch (e: HttpException) { - if (e.code() == 401) { - Toast.makeText(context, "Please sign in.", Toast.LENGTH_LONG).show() - authService.logout() - } else if (e.code() >= 500) { - Toast.makeText(context, "Something bad happened.", Toast.LENGTH_LONG).show() + when (throwable) { + is SocketTimeoutException -> showToast("Connection timed out.") + is ConnectException -> showToast("Cannot connect to server.") + is HttpException -> { + when { + (throwable.code() == 401) -> { + showToast("Please sign in.") + authService.logout() + } + (throwable.code() >= 500) -> showToast("Something bad happened.") + } + } + is Throwable -> { + Timber.e(throwable, "handleHttpError: ${throwable.message}") + showToast("Something bad happened.") } - } catch (e: Throwable) { - Timber.e(e, "handleHttpError: ${e.message}") - Toast.makeText(context, "Something bad happened.", Toast.LENGTH_LONG).show() } } + private fun showToast(msg: String) { + Toast.makeText(context, msg, Toast.LENGTH_LONG).show() + } + } diff --git a/app/src/main/kotlin/com/hana053/micropost/service/LoginServiceImpl.kt b/app/src/main/kotlin/com/hana053/micropost/service/LoginServiceImpl.kt index 432514c..db0baf5 100644 --- a/app/src/main/kotlin/com/hana053/micropost/service/LoginServiceImpl.kt +++ b/app/src/main/kotlin/com/hana053/micropost/service/LoginServiceImpl.kt @@ -4,7 +4,7 @@ import android.content.Context import android.widget.Toast import com.hana053.micropost.interactor.LoginInteractor import com.hana053.micropost.repository.AuthTokenRepository -import retrofit2.adapter.rxjava.HttpException +import retrofit2.HttpException import rx.Observable import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers @@ -25,11 +25,11 @@ class LoginServiceImpl( .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .doOnNext { authTokenRepository.set(it.token) } - .doOnError { err -> - if (err is HttpException && err.code() == 401) { - Toast.makeText(context, "Email or Password is wrong.", Toast.LENGTH_LONG).show() - } else { - httpErrorHandler.handleError(err) + .doOnError { + when { + it is HttpException && it.code() == 401 -> + Toast.makeText(context, "Email or Password is wrong.", Toast.LENGTH_LONG).show() + else -> httpErrorHandler.handleError(it) } } .onErrorResumeNext(Observable.empty()) diff --git a/app/src/main/kotlin/com/hana053/micropost/shared/avatar/AvatarView.kt b/app/src/main/kotlin/com/hana053/micropost/shared/avatar/AvatarView.kt index 98141b2..b1bf20c 100644 --- a/app/src/main/kotlin/com/hana053/micropost/shared/avatar/AvatarView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/shared/avatar/AvatarView.kt @@ -6,12 +6,14 @@ import com.squareup.picasso.Picasso class AvatarView( - private val content: ImageView + private val content: ImageView, + private val size: Int = 96 + ) { fun render(user: User) { Picasso.with(content.context) - .load(user.avatarUrl(96)) + .load(user.avatarUrl(size)) .into(content) } diff --git a/app/src/main/kotlin/com/hana053/micropost/shared/followbtn/FollowBtnService.kt b/app/src/main/kotlin/com/hana053/micropost/shared/followbtn/FollowBtnService.kt index b5f4b4d..cbecd92 100644 --- a/app/src/main/kotlin/com/hana053/micropost/shared/followbtn/FollowBtnService.kt +++ b/app/src/main/kotlin/com/hana053/micropost/shared/followbtn/FollowBtnService.kt @@ -16,32 +16,27 @@ class FollowBtnService( fun handleFollowBtnClicks(view: FollowBtnView): Observable { val obs = if (view.isFollowState()) follow(view) else unfollow(view) return obs.withBtnDisabled(view.enabled) + .doOnError { httpErrorHandler.handleError(it) } + .onErrorResumeNext { Observable.empty() } .map { view.user } } - private fun follow(view: FollowBtnView): Observable { - return relationshipInteractor.follow(view.user.id) + private fun follow(view: FollowBtnView) = + relationshipInteractor.follow(view.user.id) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .doOnNext { view.toUnfollow() } - .doOnError { httpErrorHandler.handleError(it) } - .onErrorResumeNext { Observable.empty() } - } - private fun unfollow(view: FollowBtnView): Observable { - return relationshipInteractor.unfollow(view.user.id) + private fun unfollow(view: FollowBtnView) = + relationshipInteractor.unfollow(view.user.id) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .doOnNext { view.toFollow() } - .doOnError { httpErrorHandler.handleError(it) } - .onErrorResumeNext { Observable.empty() } - } - private fun Observable.withBtnDisabled(enabled: Action1): Observable { - return Observable.using({ + private fun Observable.withBtnDisabled(enabled: Action1) = + Observable.using({ enabled.call(false) }, { this }, { enabled.call(true) }) - } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/shared/followbtn/FollowBtnView.kt b/app/src/main/kotlin/com/hana053/micropost/shared/followbtn/FollowBtnView.kt index 6949465..0e1a64f 100644 --- a/app/src/main/kotlin/com/hana053/micropost/shared/followbtn/FollowBtnView.kt +++ b/app/src/main/kotlin/com/hana053/micropost/shared/followbtn/FollowBtnView.kt @@ -30,13 +30,11 @@ class FollowBtnView( val authService = button.context.appKodein().instance() button.visibility().call(!authService.isMyself(user)) - if (user.isFollowedByMe) toUnfollow() else toFollow() + user.isFollowedByMe?.let { if(it) toUnfollow() else toFollow()} this._user = user } - fun clicks(): Observable { - return button.clicks().map { this } - } + fun clicks(): Observable = button.clicks().map { this } fun toFollow() { button.text = FOLLOW @@ -46,8 +44,6 @@ class FollowBtnView( button.text = UNFOLLOW } - fun isFollowState(): Boolean { - return button.text == FOLLOW - } + fun isFollowState() = button.text == FOLLOW } \ No newline at end of file diff --git a/app/src/main/kotlin/com/hana053/micropost/shared/posts/PostListAdapter.kt b/app/src/main/kotlin/com/hana053/micropost/shared/posts/PostListAdapter.kt index 1bc660a..87f2957 100644 --- a/app/src/main/kotlin/com/hana053/micropost/shared/posts/PostListAdapter.kt +++ b/app/src/main/kotlin/com/hana053/micropost/shared/posts/PostListAdapter.kt @@ -22,46 +22,41 @@ class PostListAdapter( val avatarClicksSubject: PublishSubject = PublishSubject.create() - override fun getItemCount(): Int { - return posts.size + class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val container: LinearLayout = view.container + val avatar: ImageView = view.img_avatar + val userName: TextView = view.tv_post_user_name + val createdAt: RelativeTimeTextView = view.tv_post_created_at + val content: TextView = view.tv_post_content } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = + LayoutInflater.from(parent.context) + .inflate(R.layout.item_posts, parent, false) + .let(::ViewHolder) + override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = posts[position] - holder.userName.text = item.user.name - holder.createdAt.setReferenceTime(item.createdAt) - holder.content.text = item.content - holder.container.tag = item - AvatarView(holder.avatar).render(item.user) - holder.avatar.setOnClickListener { - avatarClicksSubject.onNext(item.user) + holder.apply { + container.tag = item + userName.text = item.user.name + createdAt.setReferenceTime(item.createdAt) + content.text = item.content + AvatarView(avatar).render(item.user) + avatar.setOnClickListener { + avatarClicksSubject.onNext(item.user) + } } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val v = LayoutInflater.from(parent.context) - .inflate(R.layout.item_posts, parent, false) - return ViewHolder(v) - } - - class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { - val container: LinearLayout = view.container - val avatar: ImageView = view.avatar - val userName: TextView = view.userName - val createdAt: RelativeTimeTextView = view.createdAt - val content: TextView = view.content - } + override fun getItemCount(): Int = posts.size - fun getFirstItemId(): Long? { - return posts.map { it.id }.firstOrNull() - } + fun getFirstItemId(): Long? = posts.map { it.id }.firstOrNull() - fun getLastItemId(): Long? { - return posts.map { it.id }.lastOrNull() - } + fun getLastItemId(): Long? = posts.map { it.id }.lastOrNull() - fun addAll(location: Int, posts: Collection): Boolean { + fun addAll(location: Int, posts: List): Boolean { if (this.posts.addAll(location, posts)) { notifyItemRangeInserted(location, posts.size) return true diff --git a/app/src/main/res/layout/_user_detail.xml b/app/src/main/res/layout/_user_detail.xml index 55a934f..7d4cdbd 100644 --- a/app/src/main/res/layout/_user_detail.xml +++ b/app/src/main/res/layout/_user_detail.xml @@ -26,7 +26,7 @@ android:layout_height="wrap_content"> + android:layout_toEndOf="@+id/img_avatar"/>