Skip to content

Commit

Permalink
Page moved and API call changed; Add Navigation component for backdro…
Browse files Browse the repository at this point in the history
…p menu; Placeholder for News fragment; Upgrades and Material theme.

move version for play store, readme
  • Loading branch information
cloudbank committed May 4, 2020
1 parent e00a5bf commit 8ead4d9
Show file tree
Hide file tree
Showing 17 changed files with 351 additions and 191 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

### -- up to date statistics that keep up with rapidly changing covid-19 data

### Version 3.2 changelog:
* Add Navigation Component for backdrop implementation
* Placeholder for News Fragment (TBD)
* Upgrade Glide and Material, use Material theme
* API call change from page relocation

### Version 3 changelog:
* upgrade retrofit and add Kotlin coroutines support
Expand All @@ -18,6 +23,7 @@
* add Material backdrop w menu
* basic handle landscape xml


### Version 2 changelog:
* fixed data scrape for change in page
* flatten UI
Expand Down
7 changes: 5 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ android {
minSdkVersion build_versions.min_sdk
targetSdkVersion build_versions.target_sdk
multiDexEnabled true
versionCode 3.1
versionName "3.1"
versionCode 5
versionName "3.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
Expand Down Expand Up @@ -101,4 +101,7 @@ dependencies {
testImplementation deps.retrofit.mock
testImplementation deps.arch_core.testing
testImplementation deps.mockito.core
implementation 'androidx.navigation:navigation-fragment-ktx:2.0.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.0.0'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.paging.PagingRequestHelper
import com.droidteahouse.coronaTracker.repository.NetworkState
import com.droidteahouse.coronaTracker.vo.Area
import com.droidteahouse.coronaTracker.vo.NewsResponse
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import kotlinx.coroutines.Dispatchers
Expand All @@ -39,9 +40,12 @@ import retrofit2.http.GET
* API communication setup
*/
interface CoronaTrackerApi {
@GET("/wiki/2019%E2%80%9320_coronavirus_pandemic")
@GET("/wiki/COVID-19_pandemic")
suspend fun scrape(): Response<String>

@GET("")
suspend fun news(): Response<NewsResponse>


data class CoronaTrackerResponse(val data: Area)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.droidteahouse.coronaTracker.ui

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.*
import com.droidteahouse.GlideApp
import com.droidteahouse.GlideRequests
import com.droidteahouse.coronaTracker.R
import com.droidteahouse.coronaTracker.ServiceLocator
import com.droidteahouse.coronaTracker.repository.NetworkState
import kotlinx.android.synthetic.main.fragment_coronatracker.*

open class BaseFragment : Fragment() {
var network: MutableLiveData<Boolean> = MutableLiveData<Boolean>()
lateinit var glide: GlideRequests

val model: CoronaTrackerViewModel by viewModels {
object : AbstractSavedStateViewModelFactory(this, null) {
override fun <T : ViewModel?> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
val repo = ServiceLocator.instance(context!!)
.getRepository()
@Suppress("UNCHECKED_CAST")
return CoronaTrackerViewModel(repo) as T
}
}
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
glide = GlideApp.with(context!!)
}


//@todo this will not work with a VPN connection like reverse tethering to detect if the relay server is cut
fun checkNetwork(): Boolean {
var result = false
val cm = activity!!.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
val activeNetworkInfo = cm.getActiveNetworkInfo()
result = activeNetworkInfo != null && activeNetworkInfo.isConnected
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val network = cm.activeNetwork
val capabilities = cm
.getNetworkCapabilities(network)
result = capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
network.value = result
if (result == false) swipe_refresh.isRefreshing = false
return result
}

fun initSwipeToRefresh() {
swipe_refresh.setColorSchemeResources(
R.color.colorPrimary,
android.R.color.holo_green_dark,
android.R.color.holo_orange_dark,
android.R.color.holo_blue_dark)
model.refreshState.observe(this, Observer {
swipe_refresh.isRefreshing = (it == NetworkState.LOADING)
checkNetwork()
})

swipe_refresh.setOnRefreshListener {
if (checkNetwork()) {
model.refresh()
}
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,19 @@
package com.droidteahouse.coronaTracker.ui


import android.content.Context
import android.graphics.PorterDuff
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.lifecycle.*
import androidx.paging.PagedList
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.droidteahouse.GlideApp
import com.droidteahouse.GlideRequests
import androidx.lifecycle.AbstractSavedStateViewModelFactory
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.navigation.fragment.findNavController
import com.droidteahouse.backdrop.BackDropIconClickListener
import com.droidteahouse.coronaTracker.R
import com.droidteahouse.coronaTracker.ServiceLocator
import com.droidteahouse.coronaTracker.repository.NetworkState
import com.droidteahouse.coronaTracker.vo.Area
import kotlinx.android.synthetic.main.activity_coronatracker.*
import kotlinx.android.synthetic.main.main_layout.*


Expand All @@ -49,11 +38,8 @@ import kotlinx.android.synthetic.main.main_layout.*
*
*/
class CoronaTrackerActivity : AppCompatActivity() {
var network: MutableLiveData<Boolean> = MutableLiveData<Boolean>()

companion object {

}

private val model: CoronaTrackerViewModel by viewModels {
object : AbstractSavedStateViewModelFactory(this, null) {
Expand All @@ -73,14 +59,8 @@ class CoronaTrackerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_layout)
network.observe(this, Observer {
no_network.visibility = if (it == true) View.GONE else View.VISIBLE
no_network.invalidate()
})

initMenu()
initSwipeToRefresh()
initAdapter()
checkNetwork()
}

private fun initMenu() {
Expand All @@ -93,94 +73,16 @@ class CoronaTrackerActivity : AppCompatActivity() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
product_grid.background = getDrawable(R.drawable.shr_product_grid_background_shape)
}

}


//@todo this will not work with a VPN connection like reverse tethering to detect if the relay server is cut
private fun checkNetwork(): Boolean {
var result = false
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
val activeNetworkInfo = cm.getActiveNetworkInfo()
result = activeNetworkInfo != null && activeNetworkInfo.isConnected
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val network = cm.activeNetwork
val capabilities = cm
.getNetworkCapabilities(network)
result = capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
network.value = result
if (result == false) swipe_refresh.isRefreshing = result
return result
}


private fun initAdapter() {
val glide = GlideApp.with(this)
loadWorldMap(glide)
val adapter = AreaAdapter(glide) {
if (checkNetwork()) {
model.retry()
loadWorldMap(glide)
}
}
list.adapter = adapter
val horizontalDecoration = DividerItemDecoration(this,
DividerItemDecoration.VERTICAL)
val horizontalDivider = ContextCompat.getDrawable(this, R.drawable.list_divider)
horizontalDecoration.setDrawable(horizontalDivider!!)
list.addItemDecoration(horizontalDecoration)

list.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
list.setHasFixedSize(true);
list.setItemAnimator(DefaultItemAnimator())



model.areas.observe(this, Observer<PagedList<Area>> {
adapter.submitList(it) {
// Workaround for an issue where RecyclerView incorrectly uses the loading / spinner
// item added to the end of the list as an anchor during initial load.
val layoutManager = (list.layoutManager as LinearLayoutManager)
val position = layoutManager.findFirstCompletelyVisibleItemPosition()
if (position != RecyclerView.NO_POSITION) {
list.scrollToPosition(position)
}
}
})
model.networkState.observe(this, Observer {
adapter.setNetworkState(it)
})
model.worldData.observe(this, Observer {
totals.text = it
})

//product_grid.onTouchEvent()
}

private fun loadWorldMap(glide: GlideRequests) {
if (!getResources().getBoolean(R.bool.is_landscape)) {
glide.load(getString(R.string.world_map_url)).into(mapview)
mapview.setColorFilter(ContextCompat.getColor(this, R.color.colorPrimary), PorterDuff.Mode.MULTIPLY);
fun updateData(v: View) {
val nc = myNavHostFragment.findNavController()
when (v.id) {
R.id.dailyreportbtn -> nc.navigate(R.id.daily_report)
R.id.news -> nc.navigate(R.id.newsFragment)
}
}

private fun initSwipeToRefresh() {
swipe_refresh.setColorSchemeResources(
R.color.colorPrimary,
android.R.color.holo_green_dark,
android.R.color.holo_orange_dark,
android.R.color.holo_blue_dark)
model.refreshState.observe(this, Observer {
swipe_refresh.isRefreshing = it == NetworkState.LOADING
checkNetwork()
})

swipe_refresh.setOnRefreshListener {
if (checkNetwork()) {
model.refresh()
}
}
}

}
Loading

0 comments on commit 8ead4d9

Please sign in to comment.