From 2044ea273b2ba1c3ecf2aaeca296e1b833a39f5b Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Mon, 29 Mar 2021 23:11:08 +0100 Subject: [PATCH] Now sorting sat items list via LiveData switchMap --- .../look4sat/data/database/SatelliteDao.kt | 2 +- .../look4sat/data/repository/SatelliteRepo.kt | 4 +- .../ui/entriesScreen/EntriesAdapter.kt | 28 ------- .../ui/entriesScreen/EntriesFragment.kt | 5 +- .../ui/entriesScreen/EntriesViewModel.kt | 77 +++++++++++-------- 5 files changed, 48 insertions(+), 68 deletions(-) diff --git a/app/src/main/java/com/rtbishop/look4sat/data/database/SatelliteDao.kt b/app/src/main/java/com/rtbishop/look4sat/data/database/SatelliteDao.kt index 77663023..24ecdc8c 100644 --- a/app/src/main/java/com/rtbishop/look4sat/data/database/SatelliteDao.kt +++ b/app/src/main/java/com/rtbishop/look4sat/data/database/SatelliteDao.kt @@ -34,7 +34,7 @@ interface SatelliteDao { @Transaction @Query("SELECT catNum, name, isSelected FROM entries ORDER BY name ASC") - suspend fun getAllSatItems(): List + fun getItemsFlow(): Flow> @Query("SELECT tle FROM entries WHERE isSelected = 1") suspend fun getSelectedSatellites(): List diff --git a/app/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt b/app/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt index dc4074e8..c69812d0 100644 --- a/app/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt +++ b/app/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt @@ -52,8 +52,8 @@ class SatelliteRepo @Inject constructor( return satelliteDao.getTransmittersByCatNum(catNum) } - suspend fun getAllSatItems(): List { - return satelliteDao.getAllSatItems() + fun getItemsFlow(): Flow> { + return satelliteDao.getItemsFlow() } suspend fun getSelectedSatellites(): List { diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesAdapter.kt index f6cfb380..b7154434 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesAdapter.kt @@ -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() { @@ -67,36 +66,10 @@ class EntriesAdapter : RecyclerView.Adapter() { 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) { 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() { 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()) } } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt index 2b83410d..b8225aca 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt @@ -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() } } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesViewModel.kt index 0a96e380..86c85071 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesViewModel.kt @@ -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() - private val satDataState = MutableStateFlow>>(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) { - 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>>().apply { + addSource(itemsWithQuery) { value -> this.value = value } } + val satData: LiveData>> = _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 = 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) { + transModes.value = newModes + prefsRepo.saveModesSelection(newModes) + } + + private fun filterByModes(items: List, modes: List): List { + if (modes.isEmpty()) return items + return items.filter { item -> item.modes.any { mode -> mode in modes } } + } + + private fun filterByQuery(items: List, query: String): List { + 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, isSelected: Boolean) { viewModelScope.launch { satelliteRepo.updateEntriesSelection(catNums, isSelected)