From 0e962c17c2d7311b2ec8a1881ef65dd45df4ea46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Fri, 24 Aug 2018 15:48:29 +0200 Subject: [PATCH] Refactor main module (#154) --- app/build.gradle | 3 +- app/jacoco.gradle | 31 +++--- app/src/main/AndroidManifest.xml | 2 +- .../io/github/wulkanowy/di/BuilderModule.kt | 3 +- .../ui/login/options/LoginOptionsFragment.kt | 6 +- .../ui/login/options/LoginOptionsPresenter.kt | 5 +- .../github/wulkanowy/ui/main/MainActivity.kt | 97 ++++++++++++++++++- .../io/github/wulkanowy/ui/main/MainModule.kt | 50 ++++++++++ .../github/wulkanowy/ui/main/MainPresenter.kt | 29 ++++++ .../io/github/wulkanowy/ui/main/MainView.kt | 18 ++++ .../ui/main/attendance/AttendanceFragment.kt | 20 ++++ .../wulkanowy/ui/main/exam/ExamFragment.kt | 20 ++++ .../wulkanowy/ui/main/grade/GradeFragment.kt | 20 ++++ .../wulkanowy/ui/main/more/MoreFragment.kt | 20 ++++ .../ui/main/timetable/TimetableFragment.kt | 20 ++++ .../wulkanowy/ui/splash/SplashActivity.kt | 3 +- app/src/main/res/layout/activity_main.xml | 58 +++-------- .../main/res/layout/fragment_attendance.xml | 15 ++- app/src/main/res/layout/fragment_exams.xml | 13 ++- app/src/main/res/layout/fragment_grades.xml | 15 +-- .../main/res/layout/fragment_timetable.xml | 15 ++- app/src/main/res/values-pl/strings.xml | 3 +- app/src/main/res/values/strings.xml | 3 +- app/src/main/res/values/styles.xml | 2 +- .../wulkanowy/ui/main/MainPresenterTest.kt | 55 +++++++++++ build.gradle | 4 +- 26 files changed, 433 insertions(+), 97 deletions(-) create mode 100644 app/src/main/java/io/github/wulkanowy/ui/main/MainModule.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/main/MainView.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/main/exam/ExamFragment.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/main/grade/GradeFragment.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/main/more/MoreFragment.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.kt create mode 100644 app/src/test/java/io/github/wulkanowy/ui/main/MainPresenterTest.kt diff --git a/app/build.gradle b/app/build.gradle index 5c373f22..38b4c947 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -113,7 +113,6 @@ dependencies { implementation "org.apache.commons:commons-collections4:$apacheCollections" implementation "eu.davidea:flexible-adapter:$flexibleAdapter" implementation "eu.davidea:flexible-adapter-ui:$flexibleUi" - implementation "com.jakewharton:butterknife:$butterknife" implementation "com.google.dagger:dagger-android-support:$dagger2" implementation "com.aurelhubert:ahbottomnavigation:$ahbottom" implementation "com.jakewharton.threetenabp:threetenabp:$threeTenABP" @@ -126,6 +125,7 @@ dependencies { implementation 'com.android.support:multidex:1.0.3' implementation "android.arch.persistence.room:rxjava2:1.1.1" implementation 'com.github.pwittchen:reactivenetwork-rx2:2.1.0' + implementation 'com.ncapdevi:frag-nav:3.0.0-RC3' implementation("com.crashlytics.sdk.android:crashlytics:$crashlyticsSdk@aar") { transitive = true @@ -136,7 +136,6 @@ dependencies { kapt "com.google.dagger:dagger-compiler:$dagger2" kapt "com.google.dagger:dagger-android-processor:$dagger2" - kapt "com.jakewharton:butterknife-compiler:$butterknife" kapt "android.arch.persistence.room:compiler:1.1.1" debugImplementation "com.amitshekhar.android:debug-db:$debugDb" diff --git a/app/jacoco.gradle b/app/jacoco.gradle index f59b3857..45c55617 100644 --- a/app/jacoco.gradle +++ b/app/jacoco.gradle @@ -20,16 +20,18 @@ task jacocoTestReport(type: JacocoReport) { html.enabled = true } - def excludes = [ - "**/R.class", - "**/R\$*.class", - "**/*\$ViewInjector*.*", - "**/BuildConfig.*", - "**/Manifest*.*", - "**/*Test*.*", - "android/**/*.*", - "**/*Fragment.*", - "**/*Activity.*" + def excludes = ['**/R.class', + '**/R$*.class', + '**/BuildConfig.*', + '**/Manifest*.*', + '**/*Test*.*', + 'android/**/*.*', + '**/*Module.*', + '**/*Dagger*.*', + '**/*MembersInjector*.*', + '**/*_Provide*Factory*.*', + '**/*_Factory.*', + '**/*$*$*.*' ] // generated classes @@ -43,14 +45,9 @@ task jacocoTestReport(type: JacocoReport) { excludes: excludes ) - // sources - sourceDirectories = files([ - android.sourceSets.main.java.srcDirs, - "src/main/kotlin" - ]) - + sourceDirectories = files("$project.projectDir/src/main/java") executionData = fileTree( dir: project.projectDir, - includes: ["**/*.exec" , "**/*.ec"] + includes: ["**/*.exec", "**/*.ec"] ) } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5013dbc5..a4c2c947 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -34,7 +34,7 @@ view?.showLoginProgress(true) } + .doOnSubscribe { _ -> + view?.showLoginProgress(true) + view?.showActionBar(false) + } .doOnSuccess { _ -> view?.openMainView() } .subscribe({ _ -> }, { error -> errorHandler.proceed(error) }) }) diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.kt index c061680d..5b845080 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.kt @@ -2,12 +2,107 @@ package io.github.wulkanowy.ui.main import android.content.Context import android.content.Intent +import android.os.Bundle +import android.support.v4.app.Fragment +import android.support.v4.content.ContextCompat +import com.aurelhubert.ahbottomnavigation.AHBottomNavigation +import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem +import com.ncapdevi.fragnav.FragNavController +import com.ncapdevi.fragnav.FragNavController.Companion.DETACH_ON_NAVIGATE_HIDE_ON_SWITCH +import io.github.wulkanowy.R import io.github.wulkanowy.ui.base.BaseActivity +import io.github.wulkanowy.ui.main.attendance.AttendanceFragment +import io.github.wulkanowy.ui.main.exam.ExamFragment +import io.github.wulkanowy.ui.main.grade.GradeFragment +import io.github.wulkanowy.ui.main.more.MoreFragment +import io.github.wulkanowy.ui.main.timetable.TimetableFragment +import kotlinx.android.synthetic.main.activity_main.* +import javax.inject.Inject -class MainActivity : BaseActivity() { +class MainActivity : BaseActivity(), MainView, FragNavController.TransactionListener { + @Inject + lateinit var presenter: MainPresenter + + @Inject + lateinit var navController: FragNavController companion object { + const val DEFAULT_TAB = 0 + fun getStartIntent(context: Context) = Intent(context, MainActivity::class.java) } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + messageView = mainContainer + presenter.attachView(this) + navController.initialize(DEFAULT_TAB, savedInstanceState) + } + + override fun initFragmentController() { + navController.run { + rootFragments = listOf( + GradeFragment.newInstance(), + AttendanceFragment.newInstance(), + ExamFragment.newInstance(), + TimetableFragment.newInstance(), + MoreFragment.newInstance() + ) + fragmentHideStrategy = DETACH_ON_NAVIGATE_HIDE_ON_SWITCH + createEager = true + transactionListener = this@MainActivity + } + } + + override fun initBottomNav() { + mainBottomNav.run { + addItems(mutableListOf( + AHBottomNavigationItem(R.string.grades_text, R.drawable.ic_menu_grade_26dp, 0), + AHBottomNavigationItem(R.string.attendance_text, R.drawable.ic_menu_attendance_24dp, 0), + AHBottomNavigationItem(R.string.exams_text, R.drawable.ic_menu_exams_24dp, 0), + AHBottomNavigationItem(R.string.timetable_text, R.drawable.ic_menu_timetable_24dp, 0), + AHBottomNavigationItem(R.string.more_text, R.drawable.ic_menu_other_24dp, 0) + )) + accentColor = ContextCompat.getColor(context, R.color.colorPrimary) + inactiveColor = ContextCompat.getColor(context, android.R.color.black) + titleState = AHBottomNavigation.TitleState.ALWAYS_SHOW + currentItem = DEFAULT_TAB + isBehaviorTranslationEnabled = false + setOnTabSelectedListener { position, _ -> + presenter.onTabSelected(position) + } + } + } + + override fun onFragmentTransaction(fragment: Fragment?, transactionType: FragNavController.TransactionType) {} + + override fun onTabTransaction(fragment: Fragment?, index: Int) { + presenter.onMenuFragmentChange(index) + } + + override fun switchMenuFragment(position: Int) { + navController.switchTab(position) + } + + override fun setViewTitle(title: String) { + setTitle(title) + } + + override fun defaultTitle(): String = getString(R.string.activity_main_text) + + override fun mapOfTitles(): Map { + return mapOf(0 to R.string.grades_text, + 1 to R.string.attendance_text, + 2 to R.string.exams_text, + 3 to R.string.timetable_text, + 4 to R.string.more_text + ).mapValues { getString(it.value) } + } + + override fun onSaveInstanceState(outState: Bundle?) { + super.onSaveInstanceState(outState) + navController.onSaveInstanceState(outState) + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainModule.kt b/app/src/main/java/io/github/wulkanowy/ui/main/MainModule.kt new file mode 100644 index 00000000..ea37ef4e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/MainModule.kt @@ -0,0 +1,50 @@ +package io.github.wulkanowy.ui.main + +import com.ncapdevi.fragnav.FragNavController +import dagger.Module +import dagger.Provides +import dagger.android.ContributesAndroidInjector +import io.github.wulkanowy.R +import io.github.wulkanowy.di.scopes.PerActivity +import io.github.wulkanowy.di.scopes.PerFragment +import io.github.wulkanowy.ui.main.attendance.AttendanceFragment +import io.github.wulkanowy.ui.main.exam.ExamFragment +import io.github.wulkanowy.ui.main.grade.GradeFragment +import io.github.wulkanowy.ui.main.more.MoreFragment +import io.github.wulkanowy.ui.main.timetable.TimetableFragment + +@Module +abstract class MainModule { + + @Module + companion object { + + @JvmStatic + @PerActivity + @Provides + fun provideFragNavController(activity: MainActivity): FragNavController { + return FragNavController(activity.supportFragmentManager, R.id.mainFragmentContainer) + } + } + + @PerFragment + @ContributesAndroidInjector + abstract fun bindAttendanceFragment(): AttendanceFragment + + @PerFragment + @ContributesAndroidInjector + abstract fun bindExamFragment(): ExamFragment + + @PerFragment + @ContributesAndroidInjector + abstract fun bindGradeFragment(): GradeFragment + + @PerFragment + @ContributesAndroidInjector + abstract fun bindMoreFragment(): MoreFragment + + @PerFragment + @ContributesAndroidInjector + abstract fun bindTimetableFragment(): TimetableFragment +} + diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.kt new file mode 100644 index 00000000..5041b989 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.kt @@ -0,0 +1,29 @@ +package io.github.wulkanowy.ui.main + +import io.github.wulkanowy.data.ErrorHandler +import io.github.wulkanowy.ui.base.BasePresenter +import javax.inject.Inject + +class MainPresenter @Inject constructor(errorHandler: ErrorHandler) + : BasePresenter(errorHandler) { + + override fun attachView(view: MainView) { + super.attachView(view) + view.run { + initFragmentController() + initBottomNav() + } + } + + fun onTabSelected(position: Int): Boolean { + view?.switchMenuFragment(position) + return true + } + + fun onMenuFragmentChange(position: Int) { + view?.run { + setViewTitle(mapOfTitles()[position] ?: defaultTitle()) + } + } +} + diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainView.kt b/app/src/main/java/io/github/wulkanowy/ui/main/MainView.kt new file mode 100644 index 00000000..c5b3d7c2 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/MainView.kt @@ -0,0 +1,18 @@ +package io.github.wulkanowy.ui.main + +import io.github.wulkanowy.ui.base.BaseView + +interface MainView : BaseView { + + fun initFragmentController() + + fun initBottomNav() + + fun switchMenuFragment(position: Int) + + fun setViewTitle(title: String) + + fun defaultTitle(): String + + fun mapOfTitles(): Map +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.kt new file mode 100644 index 00000000..448817b1 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.kt @@ -0,0 +1,20 @@ +package io.github.wulkanowy.ui.main.attendance + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import io.github.wulkanowy.R +import io.github.wulkanowy.ui.base.BaseFragment + +class AttendanceFragment : BaseFragment() { + + companion object { + fun newInstance() = AttendanceFragment() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_attendance, container, false) + } +} + diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/exam/ExamFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/main/exam/ExamFragment.kt new file mode 100644 index 00000000..6e8ad599 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exam/ExamFragment.kt @@ -0,0 +1,20 @@ +package io.github.wulkanowy.ui.main.exam + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import io.github.wulkanowy.R +import io.github.wulkanowy.ui.base.BaseFragment + +class ExamFragment : BaseFragment() { + + companion object { + fun newInstance() = ExamFragment() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_exams, container, false) + } +} + diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/grade/GradeFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/main/grade/GradeFragment.kt new file mode 100644 index 00000000..3b70cdbc --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/grade/GradeFragment.kt @@ -0,0 +1,20 @@ +package io.github.wulkanowy.ui.main.grade + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import io.github.wulkanowy.R +import io.github.wulkanowy.ui.base.BaseFragment + +class GradeFragment : BaseFragment() { + + companion object { + fun newInstance() = GradeFragment() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_grades, container, false) + } +} + diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/more/MoreFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/main/more/MoreFragment.kt new file mode 100644 index 00000000..c1431a9b --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/more/MoreFragment.kt @@ -0,0 +1,20 @@ +package io.github.wulkanowy.ui.main.more + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import io.github.wulkanowy.R +import io.github.wulkanowy.ui.base.BaseFragment + +class MoreFragment : BaseFragment() { + + companion object { + fun newInstance() = MoreFragment() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_timetable, container, false) + } +} + diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.kt new file mode 100644 index 00000000..7cbf438b --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.kt @@ -0,0 +1,20 @@ +package io.github.wulkanowy.ui.main.timetable + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import io.github.wulkanowy.R +import io.github.wulkanowy.ui.base.BaseFragment + +class TimetableFragment : BaseFragment() { + + companion object { + fun newInstance() = TimetableFragment() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_timetable, container, false) + } +} + diff --git a/app/src/main/java/io/github/wulkanowy/ui/splash/SplashActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/splash/SplashActivity.kt index a0457855..6ea0ff0f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/splash/SplashActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/splash/SplashActivity.kt @@ -3,6 +3,7 @@ package io.github.wulkanowy.ui.splash import android.os.Bundle import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.login.LoginActivity +import io.github.wulkanowy.ui.main.MainActivity import javax.inject.Inject class SplashActivity : BaseActivity(), SplashView { @@ -26,7 +27,7 @@ class SplashActivity : BaseActivity(), SplashView { } override fun openMainActivity() { - //TODO('Not implemented) + startActivity(MainActivity.getStartIntent(this)) finish() } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 3f8473d8..af892ed4 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,53 +1,19 @@ + android:orientation="vertical"> - + - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_attendance.xml b/app/src/main/res/layout/fragment_attendance.xml index a1d578ab..d730ad85 100644 --- a/app/src/main/res/layout/fragment_attendance.xml +++ b/app/src/main/res/layout/fragment_attendance.xml @@ -1,11 +1,16 @@ + android:layout_alignParentBottom="true"> - + + diff --git a/app/src/main/res/layout/fragment_exams.xml b/app/src/main/res/layout/fragment_exams.xml index 1819be15..aa041532 100644 --- a/app/src/main/res/layout/fragment_exams.xml +++ b/app/src/main/res/layout/fragment_exams.xml @@ -1,11 +1,16 @@ - + + diff --git a/app/src/main/res/layout/fragment_grades.xml b/app/src/main/res/layout/fragment_grades.xml index 1f177a60..60458864 100644 --- a/app/src/main/res/layout/fragment_grades.xml +++ b/app/src/main/res/layout/fragment_grades.xml @@ -1,12 +1,15 @@ + android:layout_height="match_parent"> - + + diff --git a/app/src/main/res/layout/fragment_timetable.xml b/app/src/main/res/layout/fragment_timetable.xml index f78f1ab2..1c5bb6ec 100644 --- a/app/src/main/res/layout/fragment_timetable.xml +++ b/app/src/main/res/layout/fragment_timetable.xml @@ -1,11 +1,16 @@ + android:layout_alignParentBottom="true"> - + + diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 534adc10..7dc7ba95 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -32,12 +32,13 @@ Zielony Brak koloru - Aktywność dashboard + Główna aktywność Sprawdziany Oceny Frekwencja Plan lekcji Ustawienia + Więcej Ta część aplikacji jest w budowie Brak ocen diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index df9c83ba..53e317ec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -32,12 +32,13 @@ Green No color - Dashboard Activity + Main Activity Exams Grades Attendance Timetable Settings + More This section of app is under construction. No grades diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 1eb55f9d..c7506e2d 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,6 +1,6 @@ -