kopia lustrzana https://github.com/rt-bishop/Look4Sat
Various fixes to PassesFragment's ui state handling
rodzic
9fd0d5f2e2
commit
00549bbcba
|
@ -17,8 +17,10 @@
|
|||
*/
|
||||
package com.rtbishop.look4sat.presentation.passesScreen
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.LinearInterpolator
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
@ -38,8 +40,9 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
@AndroidEntryPoint
|
||||
class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesClickListener {
|
||||
|
||||
private val viewModel: PassesViewModel by viewModels()
|
||||
private lateinit var binding: FragmentPassesBinding
|
||||
private val passesViewModel: PassesViewModel by viewModels()
|
||||
private lateinit var refreshAnimator: ValueAnimator
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
@ -49,7 +52,7 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
|
|||
|
||||
private fun setupComponents() {
|
||||
val context = requireContext()
|
||||
val adapter = PassesAdapter(passesViewModel.shouldUseUTC(), this)
|
||||
val adapter = PassesAdapter(viewModel.shouldUseUTC(), this)
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
val itemDecoration = DividerItemDecoration(context, layoutManager.orientation)
|
||||
binding.run {
|
||||
|
@ -72,18 +75,34 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
|
|||
passesFab.setOnClickListener { navigateToEntries() }
|
||||
passesSettingsBtn.setOnClickListener { navigateToSettings() }
|
||||
}
|
||||
passesViewModel.passes.observe(viewLifecycleOwner) { passesResult ->
|
||||
setupObservers(adapter)
|
||||
setupAnimator()
|
||||
}
|
||||
|
||||
private fun setupObservers(adapter: PassesAdapter) {
|
||||
viewModel.passes.observe(viewLifecycleOwner) { passesResult ->
|
||||
handleNewPasses(passesResult, adapter)
|
||||
}
|
||||
passesViewModel.entries.observe(viewLifecycleOwner) { number ->
|
||||
viewModel.entries.observe(viewLifecycleOwner) { number ->
|
||||
handleEntriesNumber(number)
|
||||
}
|
||||
getNavResult<Pair<Int, Double>>(R.id.nav_passes, "prefs") { prefs ->
|
||||
passesViewModel.saveCalculationPrefs(prefs.first, prefs.second)
|
||||
passesViewModel.forceCalculation(prefs.first, prefs.second)
|
||||
viewModel.forceCalculation(prefs.first, prefs.second)
|
||||
}
|
||||
getNavResult<List<Int>>(R.id.nav_passes, "selection") { selection ->
|
||||
passesViewModel.saveSelectionAndRecalc(selection)
|
||||
viewModel.saveSelectionAndRecalc(selection)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAnimator() {
|
||||
refreshAnimator = ValueAnimator.ofFloat(0f, -360f).apply {
|
||||
duration = 875
|
||||
interpolator = LinearInterpolator()
|
||||
repeatMode = ValueAnimator.RESTART
|
||||
repeatCount = ValueAnimator.INFINITE
|
||||
addUpdateListener { anim ->
|
||||
binding.passesRefreshBtn.rotation = anim.animatedValue as Float
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,30 +117,36 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
|
|||
when (state) {
|
||||
is DataState.Success -> {
|
||||
adapter.submitList(state.data)
|
||||
binding.apply {
|
||||
passesRecycler.visibility = View.VISIBLE
|
||||
passesErrorMsg.visibility = View.INVISIBLE
|
||||
tickMainTimer(state.data)
|
||||
if (state.data.isNotEmpty()) { // show new passes list
|
||||
binding.run {
|
||||
passesRecycler.visibility = View.VISIBLE
|
||||
passesErrorMsg.visibility = View.INVISIBLE
|
||||
binding.passesRefreshBtn.isEnabled = true
|
||||
refreshAnimator.cancel()
|
||||
}
|
||||
} else { // show no passes message
|
||||
binding.run {
|
||||
passesRecycler.visibility = View.INVISIBLE
|
||||
passesErrorMsg.visibility = View.VISIBLE
|
||||
binding.passesRefreshBtn.isEnabled = true
|
||||
refreshAnimator.cancel()
|
||||
}
|
||||
}
|
||||
tickMainTimer(state.data, binding)
|
||||
}
|
||||
is DataState.Loading -> {
|
||||
binding.apply {
|
||||
binding.run {
|
||||
refreshAnimator.start()
|
||||
passesRefreshBtn.isEnabled = false
|
||||
passesTimer.text = 0L.toTimerString()
|
||||
passesRecycler.visibility = View.INVISIBLE
|
||||
passesErrorMsg.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
binding.apply {
|
||||
passesTimer.text = 0L.toTimerString()
|
||||
passesRecycler.visibility = View.INVISIBLE
|
||||
passesErrorMsg.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tickMainTimer(passes: List<SatPass>, binding: FragmentPassesBinding) {
|
||||
private fun tickMainTimer(passes: List<SatPass>) {
|
||||
if (passes.isNotEmpty()) {
|
||||
val timeNow = System.currentTimeMillis()
|
||||
try {
|
||||
|
@ -139,7 +164,7 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
|
|||
}
|
||||
|
||||
private fun refreshPasses() {
|
||||
passesViewModel.forceCalculation()
|
||||
viewModel.forceCalculation()
|
||||
}
|
||||
|
||||
private fun navigateToMap() {
|
||||
|
|
|
@ -35,7 +35,7 @@ class PassesViewModel @Inject constructor(
|
|||
) : ViewModel() {
|
||||
|
||||
private var passesProcessing: Job? = null
|
||||
private val _passes = MutableLiveData<DataState<List<SatPass>>>()
|
||||
private val _passes = MutableLiveData<DataState<List<SatPass>>>(DataState.Loading)
|
||||
val passes: LiveData<DataState<List<SatPass>>> = _passes
|
||||
val entries: LiveData<Int> = repository.getEntriesNumber().asLiveData()
|
||||
|
||||
|
@ -55,6 +55,8 @@ class PassesViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun shouldUseUTC() = settings.getUseUTC()
|
||||
|
||||
fun saveSelectionAndRecalc(selection: List<Int>) {
|
||||
viewModelScope.launch {
|
||||
repository.setEntriesSelection(selection)
|
||||
|
@ -70,18 +72,11 @@ class PassesViewModel @Inject constructor(
|
|||
viewModelScope.launch {
|
||||
_passes.postValue(DataState.Loading)
|
||||
passesProcessing?.cancelAndJoin()
|
||||
settings.setHoursAhead(hoursAhead)
|
||||
settings.setMinElevation(minElevation)
|
||||
val satellites = repository.getSelectedEntries()
|
||||
val stationPos = settings.loadStationPosition()
|
||||
predictor.forceCalculation(satellites, stationPos, timeRef, hoursAhead, minElevation)
|
||||
}
|
||||
}
|
||||
|
||||
fun shouldUseUTC(): Boolean {
|
||||
return settings.getUseUTC()
|
||||
}
|
||||
|
||||
fun saveCalculationPrefs(hoursAhead: Int, minElevation: Double) {
|
||||
settings.setHoursAhead(hoursAhead)
|
||||
settings.setMinElevation(minElevation)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,19 +44,13 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/passes_progress"
|
||||
android:visibility="invisible"
|
||||
style="@style/RecyclerProgress" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/passes_error_msg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/passes_error"
|
||||
android:textSize="@dimen/text_size_large"
|
||||
android:visibility="invisible" />
|
||||
android:textSize="@dimen/text_size_large" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
|
|
|
@ -62,8 +62,7 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
|||
|
||||
suspend fun processPasses(passList: List<SatPass>, time: Long): List<SatPass> {
|
||||
return withContext(predictorDispatcher) {
|
||||
val copiedList = passList.map { it.copy() }
|
||||
copiedList.forEach { pass ->
|
||||
passList.forEach { pass ->
|
||||
if (!pass.isDeepSpace) {
|
||||
val timeStart = pass.aosTime
|
||||
if (time > timeStart) {
|
||||
|
@ -73,7 +72,7 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
|||
}
|
||||
}
|
||||
}
|
||||
copiedList.filter { it.progress < 100 }.map { it.copy() }
|
||||
passList.filter { pass -> pass.progress < 100 }.map { it.copy() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue