Skip to content

Commit

Permalink
Merge branch 'feature/routing'
Browse files Browse the repository at this point in the history
# Conflicts:
#	app/src/main/java/com/cobeisfresh/template/di/AppModule.kt
#	app/src/main/java/com/cobeisfresh/template/di/PresentationModule.kt
#	app/src/main/java/com/cobeisfresh/template/ui/weather/presentation/WeatherViewModel.kt
#	app/src/main/java/com/cobeisfresh/template/ui/weather/view/fragments/WeatherFragment.kt
  • Loading branch information
LukaKordic committed Jul 29, 2019
2 parents d102704 + 9e8f374 commit c409654
Show file tree
Hide file tree
Showing 22 changed files with 304 additions and 61 deletions.
4 changes: 3 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
tools:ignore="AllowBackup,GoogleAppIndexingWarning">
<activity android:name=".ui.weather.view.WeatherActivity">
<activity android:name=".ui.welcome.view.WelcomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.weather.view.activities.WeatherActivity" />

</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package com.cobeisfresh.template.common.extensions

import android.content.Context
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.annotation.IdRes
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
Expand All @@ -22,6 +27,26 @@ fun View.gone() {
visibility = View.GONE
}

fun View.hideKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
}

inline fun View.onClick(crossinline onClick: () -> Unit) {
setOnClickListener { onClick() }
}

fun FragmentActivity.showFragment(fragment: Fragment, @IdRes container: Int, addToBackStack: Boolean = false) {
supportFragmentManager.beginTransaction()
.apply {
if (addToBackStack) {
addToBackStack(fragment.tag)
}
}
.replace(container, fragment)
.commitAllowingStateLoss()
}

fun FragmentActivity.goBack(){
supportFragmentManager.popBackStack()
}
2 changes: 2 additions & 0 deletions app/src/main/java/com/cobeisfresh/template/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.cobeisfresh.template.di

import androidx.appcompat.app.AppCompatActivity
import com.cobeisfresh.template.routing.AppFragmentNavigator
import com.cobeisfresh.template.common.coroutine.CoroutineContextProvider
import com.cobeisfresh.template.routing.AppNavigator
import org.koin.dsl.module

val appModule = module {
single { CoroutineContextProvider() }
single { (activity: AppCompatActivity) -> AppNavigator(activity) }
single { AppFragmentNavigator() }
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.cobeisfresh.template.di

import com.cobeisfresh.template.ui.weather.presentation.WeatherViewModel
import org.koin.androidx.viewmodel.dsl.viewModel
import com.cobeisfresh.template.ui.welcome.presentation.WelcomeViewModel
import org.koin.android.viewmodel.dsl.viewModel
import org.koin.dsl.module

val presentationModule = module {
viewModel { WeatherViewModel(get(), get()) }
viewModel { WelcomeViewModel() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.cobeisfresh.template.routing

import androidx.fragment.app.FragmentActivity
import com.cobeisfresh.template.R
import com.cobeisfresh.template.common.extensions.showFragment
import com.cobeisfresh.template.ui.weather.view.fragments.WeatherDetailsFragment

class AppFragmentNavigator : FragmentNavigator {

override fun showWeatherDetails(fragmentActivity: FragmentActivity) =
fragmentActivity.showFragment(WeatherDetailsFragment.newInstance(), R.id.fragmentContainer, true)

}

24 changes: 20 additions & 4 deletions app/src/main/java/com/cobeisfresh/template/routing/AppNavigator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,30 @@ package com.cobeisfresh.template.routing

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import com.cobeisfresh.template.ui.weather.base.BaseActivity
import com.cobeisfresh.template.ui.weather.view.WeatherActivity
import androidx.fragment.app.FragmentActivity
import com.cobeisfresh.template.R
import com.cobeisfresh.template.common.extensions.showFragment
import com.cobeisfresh.template.ui.base.BaseActivity
import com.cobeisfresh.template.ui.weather.view.activities.WeatherActivity
import com.cobeisfresh.template.ui.weather.view.fragments.WeatherDetailsFragment
import java.io.Serializable

class AppNavigator(private val activity: AppCompatActivity) : Navigator {

override fun showWeather() = navigateTo(getIntent<WeatherActivity>())
companion object {
const val SCREEN_TYPE = "screen_type"
}

override fun showWeather() = navigateTo(getIntent<WeatherActivity>().apply {
putExtra(SCREEN_TYPE, ScreenType.WEATHER)
})

private fun navigateTo(intent: Intent) = activity.startActivity(intent)

private inline fun <reified T : BaseActivity> getIntent() = Intent(activity, T::class.java)
}

}

enum class ScreenType : Serializable {
WEATHER
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.cobeisfresh.template.routing

import androidx.fragment.app.FragmentActivity

interface FragmentNavigator {

fun showWeatherDetails(fragmentActivity: FragmentActivity)

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ package com.cobeisfresh.template.routing
interface Navigator {

fun showWeather()

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.cobeisfresh.template.ui.weather.base
package com.cobeisfresh.template.ui.base

import android.view.View
import android.widget.ProgressBar
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import com.cobeisfresh.template.common.EMPTY_STRING
import com.cobeisfresh.template.common.extensions.gone
import com.cobeisfresh.template.common.extensions.snackbar
import com.cobeisfresh.template.common.extensions.visible
import com.cobeisfresh.template.common.extensions.*
import com.cobeisfresh.template.routing.AppNavigator
import org.koin.android.ext.android.inject
import org.koin.core.parameter.parametersOf
Expand All @@ -23,4 +22,12 @@ abstract class BaseActivity : AppCompatActivity() {
fun showLoading(progressBar: ProgressBar) = progressBar.visible()

fun hideLoading(progressBar: ProgressBar) = progressBar.gone()

fun addFragment(fragment: Fragment, containerId: Int, addToBackStack: Boolean = false) {
showFragment(fragment, containerId, addToBackStack)
}

override fun onBackPressed() {
if (supportFragmentManager.backStackEntryCount <= 1) finish() else goBack()
}
}
54 changes: 54 additions & 0 deletions app/src/main/java/com/cobeisfresh/template/ui/base/BaseFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.cobeisfresh.template.ui.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ProgressBar
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import com.cobeisfresh.template.common.EMPTY_STRING
import com.cobeisfresh.template.common.extensions.gone
import com.cobeisfresh.template.common.extensions.snackbar
import com.cobeisfresh.template.common.extensions.visible
import com.cobeisfresh.template.routing.AppFragmentNavigator
import com.cobeisfresh.template.routing.AppNavigator
import org.koin.android.ext.android.inject
import org.koin.core.parameter.parametersOf

abstract class BaseFragment : Fragment() {

protected val appFragmentNavigator: AppFragmentNavigator by inject()

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(getLayout(), container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewReady()
}

protected fun onBackPressed() = (activity as BaseActivity).onBackPressed()

abstract fun viewReady()

abstract fun getLayout(): Int


open fun showError(@StringRes errorMessage: Int, rootView: View) {
(activity as BaseActivity).showError(errorMessage, rootView)
}

open fun showError(errorMessage: String?, rootView: View) {
(activity as BaseActivity).showError(errorMessage, rootView)
}

open fun showLoading(progressBar: ProgressBar) {
(activity as BaseActivity).showLoading(progressBar)
}

open fun hideLoading(progressBar: ProgressBar) {
(activity as BaseActivity).hideLoading(progressBar)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.cobeisfresh.template.ui.weather.base
package com.cobeisfresh.template.ui.base

import androidx.lifecycle.ViewModel
import com.cobeisfresh.template.routing.AppNavigator
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.cobeisfresh.template.ui.weather.base
package com.cobeisfresh.template.ui.base

import com.cobeisfresh.template.ui.weather.base.ViewState.Status.*
import com.cobeisfresh.template.ui.base.ViewState.Status.*

data class ViewState<T>(val status: Status, val data: T?, val error: Throwable?) {

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.cobeisfresh.template.ui.weather.view.activities

import android.os.Bundle
import com.cobeisfresh.template.R
import com.cobeisfresh.template.routing.AppNavigator
import com.cobeisfresh.template.routing.ScreenType
import com.cobeisfresh.template.ui.base.BaseActivity
import com.cobeisfresh.template.ui.weather.view.fragments.WeatherFragment

class WeatherActivity : BaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_container)
when (intent.getSerializableExtra(AppNavigator.SCREEN_TYPE)) {
ScreenType.WEATHER -> addFragment(WeatherFragment.newInstance(), R.id.fragmentContainer, true)
else -> finish()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.cobeisfresh.template.ui.weather.view.fragments

import com.cobeisfresh.template.R
import com.cobeisfresh.template.ui.base.BaseFragment

class WeatherDetailsFragment: BaseFragment() {

override fun viewReady() {}

override fun getLayout() = R.layout.fragment_weather_details

companion object{
fun newInstance() = WeatherDetailsFragment()
}
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,44 @@
package com.cobeisfresh.template.ui.weather.view
package com.cobeisfresh.template.ui.weather.view.fragments

import android.content.Context
import android.os.Bundle
import android.view.inputmethod.InputMethodManager
import com.cobeisfresh.template.R
import com.cobeisfresh.template.common.convertKelvinToCelsius
import com.cobeisfresh.template.common.extensions.hideKeyboard
import com.cobeisfresh.template.common.extensions.onClick
import com.cobeisfresh.template.common.extensions.subscribe
import com.cobeisfresh.template.ui.weather.base.BaseActivity
import com.cobeisfresh.template.ui.weather.base.ViewState
import com.cobeisfresh.template.ui.weather.base.ViewState.Status.*
import com.cobeisfresh.template.ui.base.BaseFragment
import com.cobeisfresh.template.ui.base.ViewState
import com.cobeisfresh.template.ui.weather.presentation.WeatherViewModel
import com.example.domain.model.WeatherInfo
import kotlinx.android.synthetic.main.activity_weather.*
import org.koin.androidx.viewmodel.ext.android.viewModel
import kotlinx.android.synthetic.main.fragment_weather.*
import org.koin.android.viewmodel.ext.android.viewModel

class WeatherActivity : BaseActivity() {
class WeatherFragment : BaseFragment() {

private val viewModel: WeatherViewModel by viewModel()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_weather)

override fun viewReady() {
viewModel.getWeatherForLocation()
subscribeToData()

getWeather.onClick {
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(weatherActivityContainer.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
weatherActivityContainer.hideKeyboard()
viewModel.getWeatherForLocation(cityInput.text.toString())
}

showWeatherDetails.onClick { activity?.run { appFragmentNavigator.showWeatherDetails(this) } }
}

private fun subscribeToData() = with(viewModel) {
weatherLiveData.subscribe(this@WeatherActivity, ::handleViewState)
override fun getLayout() = R.layout.fragment_weather

private fun subscribeToData() {
viewModel.weatherLiveData.subscribe(this, ::handleViewState)
}

private fun handleViewState(viewState: ViewState<WeatherInfo>) {
with(viewState) {
when (status) {
LOADING -> showLoading(weatherLoadingProgress)
SUCCESS -> data?.run(::showWeatherData)
ERROR -> {
ViewState.Status.LOADING -> showLoading(weatherLoadingProgress)
ViewState.Status.SUCCESS -> data?.run(::showWeatherData)
ViewState.Status.ERROR -> {
hideLoading(weatherLoadingProgress)
showError(error?.message, weatherActivityContainer)
}
Expand All @@ -55,4 +52,9 @@ class WeatherActivity : BaseActivity() {
pressure.text = weatherInfo.pressure.toString()
humidity.text = weatherInfo.humidity.toString()
}

companion object {
fun newInstance() = WeatherFragment()
}
}

Loading

0 comments on commit c409654

Please sign in to comment.