mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-05 04:07:29 +00:00
Now sorting sat items list via LiveData switchMap
This commit is contained in:
1 parent
aef560942f
commit
2044ea273b
5 files changed
+48
-68
No files matched your search
@@ -34,7 +34,7 @@ interface SatelliteDao {
|
|||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT catNum, name, isSelected FROM entries ORDER BY name ASC")
|
@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")
|
@Query("SELECT tle FROM entries WHERE isSelected = 1")
|
||||||
suspend fun getSelectedSatellites(): List<Satellite>
|
suspend fun getSelectedSatellites(): List<Satellite>
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ class SatelliteRepo @Inject constructor(
|
|||||||
return satelliteDao.getTransmittersByCatNum(catNum)
|
return satelliteDao.getTransmittersByCatNum(catNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getAllSatItems(): List<SatItem> {
|
fun getItemsFlow(): Flow<List<SatItem>> {
|
||||||
return satelliteDao.getAllSatItems()
|
return satelliteDao.getItemsFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getSelectedSatellites(): List<Satellite> {
|
suspend fun getSelectedSatellites(): List<Satellite> {
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import androidx.recyclerview.widget.DiffUtil
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.rtbishop.look4sat.data.model.SatItem
|
import com.rtbishop.look4sat.data.model.SatItem
|
||||||
import com.rtbishop.look4sat.databinding.ItemSatEntryBinding
|
import com.rtbishop.look4sat.databinding.ItemSatEntryBinding
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class EntriesAdapter : RecyclerView.Adapter<EntriesAdapter.SatItemHolder>() {
|
class EntriesAdapter : RecyclerView.Adapter<EntriesAdapter.SatItemHolder>() {
|
||||||
|
|
||||||
@@ -67,36 +66,10 @@ class EntriesAdapter : RecyclerView.Adapter<EntriesAdapter.SatItemHolder>() {
|
|||||||
shouldSelectAll = !shouldSelectAll
|
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>) {
|
private fun submitCurrentItems(items: List<SatItem>) {
|
||||||
listDiffer.submitList(items)
|
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 getItemCount(): Int = listDiffer.currentList.size
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SatItemHolder {
|
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.text = item.name
|
||||||
binding.satItemCheckbox.isChecked = item.isSelected
|
binding.satItemCheckbox.isChecked = item.isSelected
|
||||||
itemView.setOnClickListener {
|
itemView.setOnClickListener {
|
||||||
item.isSelected = item.isSelected.not()
|
|
||||||
listener.updateSelection(listOf(item.catNum), 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 {
|
override fun onQueryTextChange(newText: String): Boolean {
|
||||||
entriesAdapter?.filterItems(newText)
|
viewModel.setNewQuery(newText)
|
||||||
binding?.entriesRecycler?.scrollToPosition(0)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
entriesAdapter = null
|
entriesAdapter = null
|
||||||
binding = null
|
binding = null
|
||||||
super.onDestroyView()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,9 +20,7 @@ package com.rtbishop.look4sat.ui.entriesScreen
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.*
|
||||||
import androidx.lifecycle.asLiveData
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.rtbishop.look4sat.R
|
import com.rtbishop.look4sat.R
|
||||||
import com.rtbishop.look4sat.data.model.Result
|
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.PrefsRepo
|
||||||
import com.rtbishop.look4sat.data.repository.SatelliteRepo
|
import com.rtbishop.look4sat.data.repository.SatelliteRepo
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
@@ -43,55 +42,39 @@ class EntriesViewModel @Inject constructor(
|
|||||||
private val satelliteRepo: SatelliteRepo
|
private val satelliteRepo: SatelliteRepo
|
||||||
) : ViewModel(), EntriesAdapter.EntriesClickListener {
|
) : ViewModel(), EntriesAdapter.EntriesClickListener {
|
||||||
|
|
||||||
private var allSatItems = listOf<SatItem>()
|
private val transModes = MutableLiveData(prefsRepo.loadModesSelection())
|
||||||
private val satDataState = MutableStateFlow<Result<List<SatItem>>>(Result.InProgress)
|
private val currentQuery = MutableLiveData(String())
|
||||||
val satData = satDataState.asLiveData(viewModelScope.coroutineContext)
|
private val itemsWithModes = transModes.switchMap { modes ->
|
||||||
|
liveData { satelliteRepo.getItemsFlow().collect { emit(filterByModes(it, modes)) } }
|
||||||
init {
|
|
||||||
loadAndFilterData()
|
|
||||||
}
|
}
|
||||||
|
private val itemsWithQuery = currentQuery.switchMap { query ->
|
||||||
private fun loadAndFilterData() {
|
itemsWithModes.map { items -> Result.Success(filterByQuery(items, query)) }
|
||||||
viewModelScope.launch {
|
|
||||||
allSatItems = satelliteRepo.getAllSatItems()
|
|
||||||
filterByModes(prefsRepo.loadModesSelection())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
private val _satData = MediatorLiveData<Result<List<SatItem>>>().apply {
|
||||||
private fun filterByModes(modes: List<String>) {
|
addSource(itemsWithQuery) { value -> this.value = value }
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
val satData: LiveData<Result<List<SatItem>>> = _satData
|
||||||
|
|
||||||
fun importSatDataFromFile(uri: Uri) {
|
fun importSatDataFromFile(uri: Uri) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
satDataState.value = Result.InProgress
|
_satData.value = Result.InProgress
|
||||||
try {
|
try {
|
||||||
satelliteRepo.importSatDataFromFile(uri)
|
satelliteRepo.importSatDataFromFile(uri)
|
||||||
loadAndFilterData()
|
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
satDataState.value = Result.Error(exception)
|
_satData.value = Result.Error(exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun importSatDataFromSources(sources: List<TleSource> = prefsRepo.loadDefaultSources()) {
|
fun importSatDataFromSources(sources: List<TleSource> = prefsRepo.loadDefaultSources()) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
satDataState.value = Result.InProgress
|
_satData.value = Result.InProgress
|
||||||
val updateMillis = measureTimeMillis {
|
val updateMillis = measureTimeMillis {
|
||||||
try {
|
try {
|
||||||
prefsRepo.saveTleSources(sources)
|
prefsRepo.saveTleSources(sources)
|
||||||
satelliteRepo.importSatDataFromWeb(sources)
|
satelliteRepo.importSatDataFromWeb(sources)
|
||||||
loadAndFilterData()
|
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
satDataState.value = Result.Error(exception)
|
_satData.value = Result.Error(exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Timber.d("Update from WEB took $updateMillis ms")
|
Timber.d("Update from WEB took $updateMillis ms")
|
||||||
@@ -118,7 +101,7 @@ class EntriesViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
setPositiveButton(context.getString(android.R.string.ok)) { _, _ ->
|
setPositiveButton(context.getString(android.R.string.ok)) { _, _ ->
|
||||||
filterByModes(selectedModes)
|
setNewModes(selectedModes)
|
||||||
}
|
}
|
||||||
setNeutralButton(context.getString(android.R.string.cancel)) { dialog, _ ->
|
setNeutralButton(context.getString(android.R.string.cancel)) { dialog, _ ->
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
@@ -127,6 +110,32 @@ class EntriesViewModel @Inject constructor(
|
|||||||
return dialogBuilder.create()
|
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) {
|
override fun updateSelection(catNums: List<Int>, isSelected: Boolean) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
satelliteRepo.updateEntriesSelection(catNums, isSelected)
|
satelliteRepo.updateEntriesSelection(catNums, isSelected)
|
||||||
|
|||||||
Reference in new issue
Block a user