Extracted passes ticking logic from PassesAdapter.kt

This commit is contained in:
Arty Bishop committed 2021-04-05 12:06:06 +01:00
1 parent 7b4f58dd78
commit 555c2fe626
5 files changed
+51 -59

No files matched your search

@@ -18,7 +18,6 @@
package com.rtbishop.look4sat.data.repository
import com.github.amsacode.predict4java.Satellite
import com.rtbishop.look4sat.data.model.Result
import com.rtbishop.look4sat.data.model.SatPass
import com.rtbishop.look4sat.di.DefaultDispatcher
import com.rtbishop.look4sat.utility.PrefsManager
@@ -36,13 +35,13 @@ class PassesRepo @Inject constructor(
private val prefsManager: PrefsManager,
@DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher
) {
private val _passes = MutableSharedFlow<Result<List<SatPass>>>(replay = 1)
private val _passes = MutableSharedFlow<List<SatPass>>(replay = 1)
private var selectedSatellites = emptyList<Satellite>()
val passes: SharedFlow<Result<List<SatPass>>> = _passes
val passes: SharedFlow<List<SatPass>> = _passes
suspend fun triggerCalculation(satellites: List<Satellite>, refDate: Date = Date()) {
if (satellites.isEmpty()) {
_passes.emit(Result.Error(Exception()))
_passes.emit(emptyList())
} else {
val oldCatNums = selectedSatellites.map { it.tle.catnum }
val newCatNums = satellites.map { it.tle.catnum }
@@ -52,16 +51,13 @@ class PassesRepo @Inject constructor(
suspend fun forceCalculation(satellites: List<Satellite>, refDate: Date = Date()) {
if (satellites.isEmpty()) {
_passes.emit(Result.Error(Exception()))
_passes.emit(emptyList())
} else {
_passes.emit(Result.InProgress)
withContext(defaultDispatcher) {
val allPasses = mutableListOf<SatPass>()
selectedSatellites = satellites
satellites.forEach { satellite ->
allPasses.addAll(getPasses(satellite, refDate))
}
_passes.emit(Result.Success(filterPasses(allPasses, refDate)))
satellites.forEach { satellite -> allPasses.addAll(getPasses(satellite, refDate)) }
_passes.emit(filterPasses(allPasses, refDate))
}
}
}
@@ -42,30 +42,13 @@ class PassesAdapter(private val isUTC: Boolean, private val clickListener: Passe
}
}
private val differ = AsyncListDiffer(this, diffCallback)
private var currentPasses = emptyList<SatPass>()
interface PassesClickListener {
fun navigateToPass(satPass: SatPass)
}
fun submitList(passes: List<SatPass>) {
currentPasses = passes
tickDiffer(System.currentTimeMillis())
}
fun tickDiffer(timeNow: Long) {
val copiedPasses = currentPasses.map { pass -> pass.copy() }
copiedPasses.forEach { pass ->
if (!pass.isDeepSpace) {
val timeStart = pass.aosDate.time
if (timeNow > timeStart) {
val deltaNow = timeNow.minus(timeStart).toFloat()
val deltaTotal = pass.losDate.time.minus(timeStart).toFloat()
pass.progress = ((deltaNow / deltaTotal) * 100).toInt()
}
}
}
differ.submitList(copiedPasses.filter { pass -> pass.progress < 100 })
differ.submitList(passes)
}
override fun getItemCount() = differ.currentList.size
@@ -39,7 +39,6 @@ import java.util.*
class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesClickListener {
private val viewModel: PassesViewModel by viewModels()
private var passes = listOf<SatPass>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -62,9 +61,6 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
viewModel.passes.observe(viewLifecycleOwner, { passesResult ->
handleNewPasses(passesResult, passesAdapter, binding)
})
viewModel.getAppTimer().observe(viewLifecycleOwner, { timeNow ->
tickMainTimer(timeNow, passesAdapter, binding)
})
}
private fun handleNewPasses(
@@ -74,16 +70,15 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
) {
when (result) {
is Result.Success -> {
passes = result.data
passesAdapter.submitList(passes)
passesAdapter.submitList(result.data)
binding.apply {
passesError.visibility = View.INVISIBLE
passesProgress.visibility = View.INVISIBLE
passesRecycler.visibility = View.VISIBLE
}
tickMainTimer(result.data, binding)
}
is Result.InProgress -> {
passes = emptyList()
binding.apply {
passesTimer.text = 0L.formatForTimer()
passesError.visibility = View.INVISIBLE
@@ -92,7 +87,6 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
}
}
is Result.Error -> {
passes = emptyList()
binding.apply {
passesTimer.text = 0L.formatForTimer()
passesProgress.visibility = View.INVISIBLE
@@ -103,12 +97,9 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
}
}
private fun tickMainTimer(
timeNow: Long,
passesAdapter: PassesAdapter,
binding: FragmentPassesBinding
) {
private fun tickMainTimer(passes: List<SatPass>, binding: FragmentPassesBinding) {
if (passes.isNotEmpty()) {
val timeNow = System.currentTimeMillis()
try {
val nextPass = passes.first { it.aosDate.time.minus(timeNow) > 0 }
val millisBeforeStart = nextPass.aosDate.time.minus(timeNow)
@@ -118,7 +109,6 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
val millisBeforeEnd = lastPass.losDate.time.minus(timeNow)
binding.passesTimer.text = millisBeforeEnd.formatForTimer()
}
passesAdapter.tickDiffer(timeNow)
} else {
binding.passesTimer.text = 0L.formatForTimer()
}
@@ -17,16 +17,18 @@
*/
package com.rtbishop.look4sat.ui.passesScreen
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.liveData
import androidx.lifecycle.viewModelScope
import com.rtbishop.look4sat.data.model.Result
import com.rtbishop.look4sat.data.model.SatPass
import com.rtbishop.look4sat.data.repository.PassesRepo
import com.rtbishop.look4sat.data.repository.SatelliteRepo
import com.rtbishop.look4sat.utility.PrefsManager
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.collect
import javax.inject.Inject
@HiltViewModel
@@ -36,28 +38,52 @@ class PassesViewModel @Inject constructor(
private val passesRepo: PassesRepo
) : ViewModel() {
val passes = passesRepo.passes.asLiveData(viewModelScope.coroutineContext)
private val _passes = MutableLiveData<Result<List<SatPass>>>(Result.InProgress)
private var passesProcessing: Job? = null
val passes: LiveData<Result<List<SatPass>>> = _passes
init {
viewModelScope.launch {
_passes.postValue(Result.InProgress)
passesRepo.triggerCalculation(satelliteRepo.getSelectedSatellites())
}
viewModelScope.launch {
passesRepo.passes.collect { passes ->
passesProcessing?.cancelAndJoin()
passesProcessing = viewModelScope.launch { tickPasses(passes) }
}
}
}
fun forceCalculation() {
viewModelScope.launch {
_passes.postValue(Result.InProgress)
passesProcessing?.cancelAndJoin()
passesRepo.forceCalculation(satelliteRepo.getSelectedSatellites())
}
}
fun getAppTimer() = liveData {
while (true) {
emit(System.currentTimeMillis())
delay(1000)
}
}
fun shouldUseUTC(): Boolean {
return prefsManager.shouldUseUTC()
}
private suspend fun tickPasses(passes: List<SatPass>) = withContext(Dispatchers.Default) {
var currentPasses = passes
while (isActive) {
val timeNow = System.currentTimeMillis()
currentPasses.forEach { pass ->
if (!pass.isDeepSpace) {
val timeStart = pass.aosDate.time
if (timeNow > timeStart) {
val deltaNow = timeNow.minus(timeStart).toFloat()
val deltaTotal = pass.losDate.time.minus(timeStart).toFloat()
pass.progress = ((deltaNow / deltaTotal) * 100).toInt()
}
}
}
currentPasses = currentPasses.filter { it.progress < 100 }
_passes.postValue(Result.Success(currentPasses.map { it.copy() }))
delay(1000)
}
}
}
@@ -18,7 +18,6 @@
package com.rtbishop.look4sat.ui.polarScreen
import androidx.lifecycle.*
import com.rtbishop.look4sat.data.model.Result
import com.rtbishop.look4sat.data.repository.PassesRepo
import com.rtbishop.look4sat.data.repository.SatelliteRepo
import com.rtbishop.look4sat.utility.PrefsManager
@@ -48,10 +47,8 @@ class PolarViewModel @Inject constructor(
fun getPass(catNum: Int, aosTime: Long) = liveData {
passesRepo.passes.collect { passes ->
if (passes is Result.Success) {
val pass = passes.data.find { it.catNum == catNum && it.aosDate.time == aosTime }
pass?.let { emit(it) }
}
val pass = passes.find { it.catNum == catNum && it.aosDate.time == aosTime }
pass?.let { emit(it) }
}
}