From 6b3a3b31d6964adca7f06718a94d9022a0eb9170 Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Tue, 30 Mar 2021 21:43:20 +0100 Subject: [PATCH] Final satellite entries refactoring, hopefully --- .../ui/entriesScreen/EntriesAdapter.kt | 21 +- .../ui/entriesScreen/EntriesFragment.kt | 109 ++++------ .../ui/entriesScreen/EntriesViewModel.kt | 49 +++-- app/src/main/res/layout/fragment_entries.xml | 193 ++++++++---------- app/src/main/res/values-ru/strings.xml | 3 +- app/src/main/res/values/strings.xml | 3 +- build.gradle | 2 +- 7 files changed, 160 insertions(+), 220 deletions(-) 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 b7154434..fbb34b77 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 @@ -37,8 +37,6 @@ class EntriesAdapter : RecyclerView.Adapter() { } } private val listDiffer = AsyncListDiffer(this, diffCallback) - private val allItems = mutableListOf() - private var shouldSelectAll = true private lateinit var entriesClickListener: EntriesClickListener interface EntriesClickListener { @@ -49,24 +47,7 @@ class EntriesAdapter : RecyclerView.Adapter() { entriesClickListener = listener } - fun submitAllItems(items: List) { - allItems.clear() - allItems.addAll(items) - listDiffer.submitList(items) - } - - fun selectCurrentItems() { - val newList = mutableListOf() - listDiffer.currentList.forEach { item -> - item.isSelected = shouldSelectAll - newList.add(item) - } - submitCurrentItems(newList) - entriesClickListener.updateSelection(newList.map { it.catNum }, shouldSelectAll) - shouldSelectAll = !shouldSelectAll - } - - private fun submitCurrentItems(items: List) { + fun submitItems(items: List) { listDiffer.submitList(items) } 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 b8225aca..cfbeec91 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 @@ -19,7 +19,6 @@ package com.rtbishop.look4sat.ui.entriesScreen import android.os.Bundle import android.view.View -import android.widget.SearchView import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels @@ -37,27 +36,24 @@ import com.rtbishop.look4sat.utility.getNavResult import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint -class EntriesFragment : Fragment(R.layout.fragment_entries), SearchView.OnQueryTextListener { +class EntriesFragment : Fragment(R.layout.fragment_entries) { private val viewModel: EntriesViewModel by viewModels() private val filePicker = registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> uri?.let { viewModel.importSatDataFromFile(uri) } } - private var binding: FragmentEntriesBinding? = null - private var entriesAdapter: EntriesAdapter? = null override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupComponents(view) - setupObservers() } private fun setupComponents(view: View) { - entriesAdapter = EntriesAdapter().apply { + val entriesAdapter = EntriesAdapter().apply { setEntriesClickListener(viewModel) } - binding = FragmentEntriesBinding.bind(view).apply { + val binding = FragmentEntriesBinding.bind(view).apply { entriesRecycler.apply { setHasFixedSize(true) adapter = entriesAdapter @@ -68,82 +64,49 @@ class EntriesFragment : Fragment(R.layout.fragment_entries), SearchView.OnQueryT importWeb.setOnClickListener { findNavController().navigate(R.id.nav_dialog_sources) } importFile.setOnClickListener { filePicker.launch("*/*") } selectMode.setOnClickListener { showModesDialog() } - selectAll.setOnClickListener { entriesAdapter?.selectCurrentItems() } - searchBar.setOnQueryTextListener(this@EntriesFragment) + selectAll.setOnClickListener { viewModel.selectCurrentItems() } + searchBar.setOnQueryTextListener(viewModel) } - } - - private fun setupObservers() { - viewModel.satData.observe(viewLifecycleOwner, { result -> - when (result) { - is Result.Success -> setLoaded(result.data) - is Result.InProgress -> setLoading() - is Result.Error -> setError() - } + viewModel.satData.observe(viewLifecycleOwner, { satData -> + handleSatData(satData, binding, entriesAdapter) }) - getNavResult>(R.id.nav_entries, "sources") { result -> - result.map { TleSource(it) }.let { sources -> - if (sources.isNullOrEmpty()) { - viewModel.importSatDataFromSources() - } else { - viewModel.importSatDataFromSources(sources) - } - } + getNavResult>(R.id.nav_entries, "sources") { navResult -> + handleNavResult(navResult) } } - private fun setLoaded(items: List) { - if (items.isEmpty()) { - binding?.apply { - entriesEmptyError.visibility = View.VISIBLE - entriesProgress.visibility = View.INVISIBLE - entriesRecycler.visibility = View.INVISIBLE - } - } else { - entriesAdapter?.submitAllItems(items) - binding?.apply { - entriesEmptyError.visibility = View.INVISIBLE - entriesProgress.visibility = View.INVISIBLE - entriesRecycler.visibility = View.VISIBLE - entriesRecycler.scrollToPosition(0) - } - } - } - - private fun setLoading() { - binding?.apply { - entriesEmptyError.visibility = View.INVISIBLE - entriesProgress.visibility = View.VISIBLE - entriesRecycler.visibility = View.INVISIBLE - } - } - - private fun setError() { - binding?.apply { - entriesEmptyError.visibility = View.INVISIBLE - entriesProgress.visibility = View.INVISIBLE - entriesRecycler.visibility = View.VISIBLE - } - val errorMsg = getString(R.string.entries_update_error) - Snackbar.make(requireView(), errorMsg, Snackbar.LENGTH_SHORT).show() - } - private fun showModesDialog() { viewModel.createModesDialog(requireContext()).show() } - override fun onQueryTextSubmit(query: String): Boolean { - return true + private fun handleSatData( + result: Result>, + binding: FragmentEntriesBinding, + entriesAdapter: EntriesAdapter + ) { + when (result) { + is Result.Success -> { + entriesAdapter.submitItems(result.data) + binding.entriesProgress.visibility = View.INVISIBLE + binding.entriesRecycler.visibility = View.VISIBLE + binding.entriesRecycler.scrollToPosition(0) + } + is Result.InProgress -> { + binding.entriesProgress.visibility = View.VISIBLE + binding.entriesRecycler.visibility = View.INVISIBLE + } + is Result.Error -> { + binding.entriesProgress.visibility = View.INVISIBLE + binding.entriesRecycler.visibility = View.VISIBLE + val errorMsg = getString(R.string.entries_update_error) + Snackbar.make(requireView(), errorMsg, Snackbar.LENGTH_SHORT).show() + } + } } - override fun onQueryTextChange(newText: String): Boolean { - viewModel.setNewQuery(newText) - return true - } - - override fun onDestroyView() { - super.onDestroyView() - entriesAdapter = null - binding = null + private fun handleNavResult(result: List) { + result.map { sourceUrl -> TleSource(sourceUrl) }.let { sources -> + viewModel.importSatDataFromSources(sources) + } } } 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 86c85071..bc78756f 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 @@ -19,6 +19,7 @@ package com.rtbishop.look4sat.ui.entriesScreen import android.content.Context import android.net.Uri +import android.widget.SearchView import androidx.appcompat.app.AlertDialog import androidx.lifecycle.* import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -40,7 +41,7 @@ import kotlin.system.measureTimeMillis class EntriesViewModel @Inject constructor( private val prefsRepo: PrefsRepo, private val satelliteRepo: SatelliteRepo -) : ViewModel(), EntriesAdapter.EntriesClickListener { +) : ViewModel(), EntriesAdapter.EntriesClickListener, SearchView.OnQueryTextListener { private val transModes = MutableLiveData(prefsRepo.loadModesSelection()) private val currentQuery = MutableLiveData(String()) @@ -53,6 +54,7 @@ class EntriesViewModel @Inject constructor( private val _satData = MediatorLiveData>>().apply { addSource(itemsWithQuery) { value -> this.value = value } } + private var shouldSelectAll = true val satData: LiveData>> = _satData fun importSatDataFromFile(uri: Uri) { @@ -66,13 +68,15 @@ class EntriesViewModel @Inject constructor( } } - fun importSatDataFromSources(sources: List = prefsRepo.loadDefaultSources()) { + fun importSatDataFromSources(sources: List) { viewModelScope.launch { _satData.value = Result.InProgress + val satSources = if (sources.isNotEmpty()) sources + else prefsRepo.loadDefaultSources() val updateMillis = measureTimeMillis { try { - prefsRepo.saveTleSources(sources) - satelliteRepo.importSatDataFromWeb(sources) + prefsRepo.saveTleSources(satSources) + satelliteRepo.importSatDataFromWeb(satSources) } catch (exception: Exception) { _satData.value = Result.Error(exception) } @@ -81,6 +85,20 @@ class EntriesViewModel @Inject constructor( } } + fun selectCurrentItems() { + val newList = mutableListOf() + val currentValue = _satData.value + if (currentValue is Result.Success) { + currentValue.data.forEach { item -> + item.isSelected = shouldSelectAll + newList.add(item) + } + } + _satData.value = Result.Success(newList) + updateSelection(newList.map { it.catNum }, shouldSelectAll) + shouldSelectAll = !shouldSelectAll + } + fun createModesDialog(context: Context): AlertDialog { val modes = arrayOf( "AFSK", "AFSK S-Net", "AFSK SALSAT", "AHRPT", "AM", "APT", "BPSK", "BPSK PMT-A3", @@ -101,7 +119,8 @@ class EntriesViewModel @Inject constructor( } } setPositiveButton(context.getString(android.R.string.ok)) { _, _ -> - setNewModes(selectedModes) + transModes.value = selectedModes + prefsRepo.saveModesSelection(selectedModes) } setNeutralButton(context.getString(android.R.string.cancel)) { dialog, _ -> dialog.dismiss() @@ -110,13 +129,17 @@ class EntriesViewModel @Inject constructor( return dialogBuilder.create() } - fun setNewQuery(newQuery: String) { - currentQuery.value = newQuery + override fun onQueryTextSubmit(query: String): Boolean { + return true } - private fun setNewModes(newModes: List) { - transModes.value = newModes - prefsRepo.saveModesSelection(newModes) + override fun onQueryTextChange(newText: String): Boolean { + currentQuery.value = newText + return true + } + + override fun updateSelection(catNums: List, isSelected: Boolean) { + viewModelScope.launch { satelliteRepo.updateEntriesSelection(catNums, isSelected) } } private fun filterByModes(items: List, modes: List): List { @@ -135,10 +158,4 @@ class EntriesViewModel @Inject constructor( } } } - - override fun updateSelection(catNums: List, isSelected: Boolean) { - viewModelScope.launch { - satelliteRepo.updateEntriesSelection(catNums, isSelected) - } - } } diff --git a/app/src/main/res/layout/fragment_entries.xml b/app/src/main/res/layout/fragment_entries.xml index d138acc6..a3abb5d6 100644 --- a/app/src/main/res/layout/fragment_entries.xml +++ b/app/src/main/res/layout/fragment_entries.xml @@ -1,120 +1,101 @@ - - + - + - + - + - + - + - + - + - - - - - - - - - + + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a43b9887..df632680 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -16,8 +16,7 @@ Только протокол HTTPS Обновить спутники: - Поиск по имени / Id - Пожалуйста, обновите спутники + Имя / Номер Ошибка обновления спутников Выберите модуляцию трансивера diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c0ec53b2..b28e029d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -19,8 +19,7 @@ Protocol HTTPS only TLE data update: - Search by Name / Id - Please update TLE data + Name / Id Error importing satellite data Choose transceiver mode diff --git a/build.gradle b/build.gradle index fe6a072e..8ca9ed2f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { gradle_version = '4.1.3' - gradle_plugin_version = '1.4.31' + gradle_plugin_version = '1.4.32' material_version = '1.3.0' constraint_layout_version = '2.0.4' lifecycle_version = '2.3.0'