Now sorting sat items list via LiveData switchMap

This commit is contained in:
Arty Bishop committed 2021-03-29 23:11:08 +01:00
1 parent aef560942f
commit 2044ea273b
5 files changed
+48 -68

No files matched your search

@@ -34,7 +34,7 @@ interface SatelliteDao {
@Transaction
@Query("SELECT catNum, name, isSelected FROM entries ORDER BY name ASC")
suspend fun getAllSatItems(): List<SatItem>
fun getItemsFlow(): Flow<List<SatItem>>
@Query("SELECT tle FROM entries WHERE isSelected = 1")
suspend fun getSelectedSatellites(): List<Satellite>
@@ -52,8 +52,8 @@ class SatelliteRepo @Inject constructor(
return satelliteDao.getTransmittersByCatNum(catNum)
}
suspend fun getAllSatItems(): List<SatItem> {
return satelliteDao.getAllSatItems()
fun getItemsFlow(): Flow<List<SatItem>> {
return satelliteDao.getItemsFlow()
}
suspend fun getSelectedSatellites(): List<Satellite> {
@@ -24,7 +24,6 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.rtbishop.look4sat.data.model.SatItem
import com.rtbishop.look4sat.databinding.ItemSatEntryBinding
import java.util.*
class EntriesAdapter : RecyclerView.Adapter<EntriesAdapter.SatItemHolder>() {
@@ -67,36 +66,10 @@ class EntriesAdapter : RecyclerView.Adapter<EntriesAdapter.SatItemHolder>() {
shouldSelectAll = !shouldSelectAll
}
fun filterItems(query: String) {
if (query.isEmpty()) {
submitCurrentItems(allItems)
} else {
try {
filterByCatNum(query.toInt())
} catch (e: NumberFormatException) {
filterByName(query)
}
}
shouldSelectAll = true
}
private fun submitCurrentItems(items: List<SatItem>) {
listDiffer.submitList(items)
}
private fun filterByCatNum(catNum: Int) {
submitCurrentItems(allItems.filter { it.catNum == catNum })
}
private fun filterByName(name: String) {
val satName = name.toLowerCase(Locale.getDefault())
val filteredItems = allItems.filter { item ->
val itemName = item.name.toLowerCase(Locale.getDefault())
itemName.contains(satName)
}
submitCurrentItems(filteredItems)
}
override fun getItemCount(): Int = listDiffer.currentList.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SatItemHolder {
@@ -114,7 +87,6 @@ class EntriesAdapter : RecyclerView.Adapter<EntriesAdapter.SatItemHolder>() {
binding.satItemCheckbox.text = item.name
binding.satItemCheckbox.isChecked = item.isSelected
itemView.setOnClickListener {
item.isSelected = item.isSelected.not()
listener.updateSelection(listOf(item.catNum), item.isSelected.not())
}
}
@@ -137,14 +137,13 @@ class EntriesFragment : Fragment(R.layout.fragment_entries), SearchView.OnQueryT
}
override fun onQueryTextChange(newText: String): Boolean {
entriesAdapter?.filterItems(newText)
binding?.entriesRecycler?.scrollToPosition(0)
viewModel.setNewQuery(newText)
return true
}
override fun onDestroyView() {
super.onDestroyView()
entriesAdapter = null
binding = null
super.onDestroyView()
}
}
@@ -20,9 +20,7 @@ package com.rtbishop.look4sat.ui.entriesScreen
import android.content.Context
import android.net.Uri
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.*
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.data.model.Result
@@ -31,9 +29,10 @@ import com.rtbishop.look4sat.data.model.TleSource
import com.rtbishop.look4sat.data.repository.PrefsRepo
import com.rtbishop.look4sat.data.repository.SatelliteRepo
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.*
import javax.inject.Inject
import kotlin.system.measureTimeMillis
@@ -43,55 +42,39 @@ class EntriesViewModel @Inject constructor(
private val satelliteRepo: SatelliteRepo
) : ViewModel(), EntriesAdapter.EntriesClickListener {
private var allSatItems = listOf<SatItem>()
private val satDataState = MutableStateFlow<Result<List<SatItem>>>(Result.InProgress)
val satData = satDataState.asLiveData(viewModelScope.coroutineContext)
init {
loadAndFilterData()
private val transModes = MutableLiveData(prefsRepo.loadModesSelection())
private val currentQuery = MutableLiveData(String())
private val itemsWithModes = transModes.switchMap { modes ->
liveData { satelliteRepo.getItemsFlow().collect { emit(filterByModes(it, modes)) } }
}
private fun loadAndFilterData() {
viewModelScope.launch {
allSatItems = satelliteRepo.getAllSatItems()
filterByModes(prefsRepo.loadModesSelection())
}
private val itemsWithQuery = currentQuery.switchMap { query ->
itemsWithModes.map { items -> Result.Success(filterByQuery(items, query)) }
}
private fun filterByModes(modes: List<String>) {
if (modes.isEmpty()) {
satDataState.value = Result.Success(allSatItems)
} else {
val itemsWithModes = allSatItems.filter { item ->
item.modes.any { mode -> mode in modes }
}
satDataState.value = Result.Success(itemsWithModes)
}
prefsRepo.saveModesSelection(modes)
private val _satData = MediatorLiveData<Result<List<SatItem>>>().apply {
addSource(itemsWithQuery) { value -> this.value = value }
}
val satData: LiveData<Result<List<SatItem>>> = _satData
fun importSatDataFromFile(uri: Uri) {
viewModelScope.launch {
satDataState.value = Result.InProgress
_satData.value = Result.InProgress
try {
satelliteRepo.importSatDataFromFile(uri)
loadAndFilterData()
} catch (exception: Exception) {
satDataState.value = Result.Error(exception)
_satData.value = Result.Error(exception)
}
}
}
fun importSatDataFromSources(sources: List<TleSource> = prefsRepo.loadDefaultSources()) {
viewModelScope.launch {
satDataState.value = Result.InProgress
_satData.value = Result.InProgress
val updateMillis = measureTimeMillis {
try {
prefsRepo.saveTleSources(sources)
satelliteRepo.importSatDataFromWeb(sources)
loadAndFilterData()
} catch (exception: Exception) {
satDataState.value = Result.Error(exception)
_satData.value = Result.Error(exception)
}
}
Timber.d("Update from WEB took $updateMillis ms")
@@ -118,7 +101,7 @@ class EntriesViewModel @Inject constructor(
}
}
setPositiveButton(context.getString(android.R.string.ok)) { _, _ ->
filterByModes(selectedModes)
setNewModes(selectedModes)
}
setNeutralButton(context.getString(android.R.string.cancel)) { dialog, _ ->
dialog.dismiss()
@@ -127,6 +110,32 @@ class EntriesViewModel @Inject constructor(
return dialogBuilder.create()
}
fun setNewQuery(newQuery: String) {
currentQuery.value = newQuery
}
private fun setNewModes(newModes: List<String>) {
transModes.value = newModes
prefsRepo.saveModesSelection(newModes)
}
private fun filterByModes(items: List<SatItem>, modes: List<String>): List<SatItem> {
if (modes.isEmpty()) return items
return items.filter { item -> item.modes.any { mode -> mode in modes } }
}
private fun filterByQuery(items: List<SatItem>, query: String): List<SatItem> {
if (query.isBlank()) return items
return try {
items.filter { it.catNum == query.toInt() }
} catch (e: Exception) {
items.filter { item ->
val itemName = item.name.toLowerCase(Locale.getDefault())
itemName.contains(query.toLowerCase(Locale.getDefault()))
}
}
}
override fun updateSelection(catNums: List<Int>, isSelected: Boolean) {
viewModelScope.launch {
satelliteRepo.updateEntriesSelection(catNums, isSelected)