Skip to content

Commit

Permalink
Merge pull request #17 from ch8n/network_connectivity
Browse files Browse the repository at this point in the history
Add Network connectivity State #17
  • Loading branch information
Spikeysanju authored Oct 4, 2020
2 parents 80a7441 + 55d3a60 commit c4c3377
Show file tree
Hide file tree
Showing 12 changed files with 508 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@
package www.thecodemonks.techbytes.ui.articles

import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
Expand All @@ -45,6 +49,7 @@ import www.thecodemonks.techbytes.ui.adapter.CategoryAdapter
import www.thecodemonks.techbytes.ui.adapter.NewsAdapter
import www.thecodemonks.techbytes.ui.base.BaseActivity
import www.thecodemonks.techbytes.ui.viewmodel.ArticleViewModel
import www.thecodemonks.techbytes.utils.Animations
import www.thecodemonks.techbytes.utils.Constants.NY_BUSINESS
import www.thecodemonks.techbytes.utils.Constants.NY_EDUCATION
import www.thecodemonks.techbytes.utils.Constants.NY_SCIENCE
Expand Down Expand Up @@ -130,6 +135,17 @@ class ArticlesFragment : Fragment(R.layout.fragment_articles) {
)
}

var lastOnlineStatus = true // this flag is required to block showing of onlineStatus on startup
viewModel.networkObserver.observe(viewLifecycleOwner, Observer { isConnected ->
if (lastOnlineStatus != isConnected) {
lastOnlineStatus = isConnected
if (isConnected) {
container_network_status.setOnlineBehaviour()
} else {
container_network_status.setOfflineBehaviour()
}
}
})

}

Expand Down Expand Up @@ -185,4 +201,84 @@ class ArticlesFragment : Fragment(R.layout.fragment_articles) {
}
}


private val networkAutoDismissHandler = Handler()

private fun LinearLayout.setOnlineBehaviour() {

fun applyTheme() {
setBackgroundColor(
ContextCompat.getColor(
requireContext(),
R.color.colorStatusConnected
)
)
val onlineDrawable =
ContextCompat.getDrawable(requireContext(), R.drawable.ic_internet_on)
text_network_status.setCompoundDrawablesWithIntrinsicBounds(
onlineDrawable,
null,
null,
null
)
text_network_status.text = getString(R.string.text_connectivity)
}

if (!isVisible) {
//play expanding animation
Animations.expand(container_network_status)
applyTheme()
} else {
//play fade out and in animation
Animations.fadeOutFadeIn(text_network_status) {
//on fadeInStarted
applyTheme()
}
}

networkAutoDismissHandler.postDelayed({
if (viewModel.networkObserver.value == true) {
Animations.collapse(this)
}
}, 3000)

}

private fun LinearLayout.setOfflineBehaviour() {
networkAutoDismissHandler.removeCallbacksAndMessages(null)

fun applyTheme() {
setBackgroundColor(
ContextCompat.getColor(
requireContext(),
R.color.colorStatusNotConnected
)
)
val onlineDrawable =
ContextCompat.getDrawable(requireContext(), R.drawable.ic_internet_off)
text_network_status.setCompoundDrawablesWithIntrinsicBounds(
onlineDrawable,
null,
null,
null
)
text_network_status.text = getString(R.string.text_no_connectivity)
}


if (!isVisible) {
//play expanding animation
Animations.expand(container_network_status)
applyTheme()
} else {
//play fade out and in animation
Animations.fadeOutFadeIn(text_network_status) {
//on fadeInStarted
applyTheme()
}
}


}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,29 @@ import www.thecodemonks.techbytes.datastore.UIModePreference
import www.thecodemonks.techbytes.model.Article
import www.thecodemonks.techbytes.repo.Repo
import www.thecodemonks.techbytes.utils.Constants
import www.thecodemonks.techbytes.utils.NetworkManager


class ArticleViewModel(application: Application, private val repo: Repo) :
AndroidViewModel(application) {
class ArticleViewModel(
application: Application,
private val repo: Repo,
) : AndroidViewModel(application) {

private val _articles = MutableLiveData<List<Article>>()
val articles: LiveData<List<Article>>
get() = _articles

private val networkManager = NetworkManager(application)
val networkObserver = networkManager.observeConnectionStatus

// DataStore
private val uiDataStore = UIModePreference(application)

val currentTopic: MutableLiveData<String> by lazy {
MutableLiveData<String>().defaultTopic(Constants.NY_TECH)
}


// save article
fun upsertArticle(article: Article) = viewModelScope.launch {
repo.upsertArticle(article)
Expand Down
136 changes: 136 additions & 0 deletions app/src/main/java/www/thecodemonks/techbytes/utils/Animations.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
*
* * MIT License
* *
* * Copyright (c) 2020 Spikey Sanju
* *
* * Permission is hereby granted, free of charge, to any person obtaining a copy
* * of this software and associated documentation files (the "Software"), to deal
* * in the Software without restriction, including without limitation the rights
* * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* * copies of the Software, and to permit persons to whom the Software is
* * furnished to do so, subject to the following conditions:
* *
* * The above copyright notice and this permission notice shall be included in all
* * copies or substantial portions of the Software.
* *
* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* * SOFTWARE.
*
*/

package www.thecodemonks.techbytes.utils

import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.Transformation


/**
* Provides various view animations.
*
* Author : [https://github.com/ch8n]
* website : [https://chetangupta.net]
* Creation Date : 4-08-2020
*/
object Animations {

fun fadeOutFadeIn(v: View, onFadeInStart: () -> Unit = {}) {

val fadeOut = ObjectAnimator
.ofFloat(v, View.ALPHA, 1f, 0f)
.setDuration(200)

val fadeIn = ObjectAnimator
.ofFloat(v, View.ALPHA, 0f, 1f)
.setDuration(200)

fadeIn.addListener(object : AnimationCallback() {
override fun onAnimationStart(animation: Animator?) {
super.onAnimationStart(animation)
onFadeInStart.invoke()
}
})

val animatorSet = AnimatorSet();
animatorSet.playSequentially(
fadeOut,
fadeIn
);
animatorSet.start()

}


fun collapse(view: View) {
val initialHeight = view.measuredHeight
val animation: Animation = object : Animation() {
override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
if (interpolatedTime == 1f) {
view.visibility = View.GONE
} else {
view.layoutParams.height =
initialHeight - (initialHeight * interpolatedTime).toInt()
view.requestLayout()
}
}

override fun willChangeBounds(): Boolean {
return true
}
}

animation.duration = 500L
view.startAnimation(animation)
}


fun expand(view: View) {
view.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
val targetHeight = view.measuredHeight
view.layoutParams.height = 0
view.visibility = View.VISIBLE
val animation: Animation = object : Animation() {
override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
view.layoutParams.height =
if (interpolatedTime == 1f) ViewGroup.LayoutParams.WRAP_CONTENT else (targetHeight * interpolatedTime).toInt()
view.requestLayout()
}

override fun willChangeBounds(): Boolean {
return true
}
}

animation.duration = 500L
view.startAnimation(animation)
}

private abstract class AnimationCallback : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator?) {

}

override fun onAnimationEnd(animation: Animator?) {

}

override fun onAnimationCancel(animation: Animator?) {

}

override fun onAnimationRepeat(animation: Animator?) {

}
}

}
Loading

0 comments on commit c4c3377

Please sign in to comment.