Further code refactoring in Repository.kt and EntriesFragment.kt

This commit is contained in:
Arty Bishop committed 2020-10-06 23:24:16 +01:00
1 parent 58fe352e30
commit 6b39a6759a
16 files changed
+231 -341

No files matched your search

-1
View File
@@ -63,7 +63,6 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "com.google.android.material:material:$material_version"
implementation "androidx.appcompat:appcompat:$app_compat_version"
implementation "androidx.constraintlayout:constraintlayout:$constraint_layout_version"
implementation "androidx.core:core-ktx:$ktx_version"
implementation "androidx.preference:preference:$preference_version"
@@ -21,6 +21,7 @@ package com.rtbishop.look4sat.repo
import android.content.ContentResolver
import android.net.Uri
import androidx.lifecycle.LiveData
import com.github.amsacode.predict4java.TLE
import com.rtbishop.look4sat.data.SatEntry
import com.rtbishop.look4sat.data.SatTrans
@@ -45,33 +46,37 @@ class DefaultRepository @Inject constructor(
private val transDao: TransDao
) : Repository {
override fun getSources(): LiveData<List<TleSource>> {
return sourcesDao.getSources()
}
override suspend fun updateSources(sources: List<TleSource>) {
sourcesDao.clearSources()
sourcesDao.insertSources(sources)
}
////////////////////////////////////////////////////////////////////////////////////////////////
override fun getAllEntries(): LiveData<List<SatEntry>> {
return entriesDao.getAllEntries()
}
override fun getSelectedEntries(): LiveData<List<SatEntry>> {
return entriesDao.getSelectedEntries()
}
override suspend fun updateEntriesFromFile(tleUri: Uri) {
withContext(Dispatchers.IO) {
resolver.openInputStream(tleUri)?.use { stream ->
val tleList = TLE.importSat(stream)
val entries = tleList.map { SatEntry(it) }
clearEntries()
insertEntries(entries)
entriesDao.clearEntries()
entriesDao.insertEntries(entries)
}
}
}
override suspend fun updateEntriesFromUrl(urlList: List<TleSource>) {
withContext(Dispatchers.IO) {
val streams = fetchTleStreams(urlList)
val entries = mutableListOf<SatEntry>()
streams.forEach {
val list = TLE.importSat(it).map { tle -> SatEntry(tle) }
entries.addAll(list)
}
clearEntries()
insertEntries(entries)
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
override suspend fun fetchTleStreams(urlList: List<TleSource>): List<InputStream> =
withContext(Dispatchers.IO) {
val streams = mutableListOf<InputStream>()
urlList.withIndex().forEach {
@@ -79,23 +84,15 @@ class DefaultRepository @Inject constructor(
val stream = client.newCall(request).execute().body?.byteStream()
stream?.let { inputStream -> streams.add(inputStream) }
}
return@withContext streams
val entries = mutableListOf<SatEntry>()
streams.forEach {
val list = TLE.importSat(it).map { tle -> SatEntry(tle) }
entries.addAll(list)
}
entriesDao.clearEntries()
entriesDao.insertEntries(entries)
}
override suspend fun fetchTransmitters(): List<SatTrans> {
return api.fetchTransList()
}
override suspend fun insertEntries(entries: List<SatEntry>) {
entriesDao.insertEntries(entries)
}
override suspend fun getAllEntries(): List<SatEntry> {
return entriesDao.getAllEntries()
}
override suspend fun getSelectedEntries(): List<SatEntry> {
return entriesDao.getSelectedEntries()
}
override suspend fun updateEntriesSelection(catNumList: List<Int>) {
@@ -103,35 +100,14 @@ class DefaultRepository @Inject constructor(
catNumList.forEach { entriesDao.updateEntrySelection(it) }
}
override suspend fun clearEntries() {
entriesDao.clearEntries()
}
////////////////////////////////////////////////////////////////////////////////////////////////
override suspend fun updateTransmitters() {
transDao.clearTransmitters()
transDao.insertTransmitters(api.fetchTransList())
}
override suspend fun getTransmittersByCatNum(catNum: Int): List<SatTrans> {
return transDao.getTransmittersForCatNum(catNum)
}
override suspend fun clearTransmitters() {
transDao.clearTransmitters()
}
////////////////////////////////////////////////////////////////////////////////////////////////
override suspend fun updateSources(sources: List<TleSource>) {
clearSources()
sourcesDao.insertSources(sources)
}
override suspend fun getSources(): List<TleSource> {
return sourcesDao.getSources()
}
override suspend fun clearSources() {
sourcesDao.clearSources()
}
}
@@ -1,46 +1,32 @@
package com.rtbishop.look4sat.repo
import android.net.Uri
import androidx.lifecycle.LiveData
import com.rtbishop.look4sat.data.SatEntry
import com.rtbishop.look4sat.data.SatTrans
import com.rtbishop.look4sat.data.TleSource
import java.io.InputStream
interface Repository {
fun getSources(): LiveData<List<TleSource>>
suspend fun updateSources(sources: List<TleSource>)
////////////////////////////////////////////////////////////////////////////////////////////////
fun getAllEntries(): LiveData<List<SatEntry>>
fun getSelectedEntries(): LiveData<List<SatEntry>>
suspend fun updateEntriesFromFile(tleUri: Uri)
suspend fun updateEntriesFromUrl(urlList: List<TleSource>)
////////////////////////////////////////////////////////////////////////////////////////////////
suspend fun fetchTleStreams(urlList: List<TleSource>): List<InputStream>
suspend fun fetchTransmitters(): List<SatTrans>
suspend fun insertEntries(entries: List<SatEntry>)
suspend fun getAllEntries(): List<SatEntry>
suspend fun getSelectedEntries(): List<SatEntry>
suspend fun updateEntriesSelection(catNumList: List<Int>)
suspend fun clearEntries()
////////////////////////////////////////////////////////////////////////////////////////////////
suspend fun updateTransmitters()
suspend fun getTransmittersByCatNum(catNum: Int): List<SatTrans>
suspend fun clearTransmitters()
////////////////////////////////////////////////////////////////////////////////////////////////
suspend fun updateSources(sources: List<TleSource>)
suspend fun getSources(): List<TleSource>
suspend fun clearSources()
}
@@ -19,6 +19,7 @@
package com.rtbishop.look4sat.repo.local
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
@@ -32,10 +33,10 @@ interface EntriesDao {
suspend fun insertEntries(entries: List<SatEntry>)
@Query("SELECT * FROM entries ORDER BY name ASC")
suspend fun getAllEntries(): List<SatEntry>
fun getAllEntries(): LiveData<List<SatEntry>>
@Query("SELECT * FROM entries WHERE isSelected = 1 ORDER BY name ASC")
suspend fun getSelectedEntries(): List<SatEntry>
fun getSelectedEntries(): LiveData<List<SatEntry>>
@Query("UPDATE entries SET isSelected = 1 WHERE catNum == :catNum")
suspend fun updateEntrySelection(catNum: Int)
@@ -1,5 +1,6 @@
package com.rtbishop.look4sat.repo.local
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
@@ -13,7 +14,7 @@ interface SourcesDao {
suspend fun insertSources(sources: List<TleSource>)
@Query("SELECT * FROM sources")
suspend fun getSources(): List<TleSource>
fun getSources(): LiveData<List<TleSource>>
@Query("DELETE FROM sources")
suspend fun clearSources()
@@ -27,5 +27,6 @@ class MainActivity : AppCompatActivity() {
binding.navBottom.setupWithNavController(navHost.navController)
(application as Look4SatApp).appComponent.inject(this)
viewModel = ViewModelProvider(this, factory).get(SharedViewModel::class.java)
viewModel.setDefaultTleSources()
}
}
@@ -32,7 +32,6 @@ import com.rtbishop.look4sat.utility.PrefsManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@@ -43,62 +42,34 @@ class SharedViewModel @Inject constructor(
private val repository: Repository
) : ViewModel() {
private val _satPassList = MutableLiveData<Result<MutableList<SatPass>>>()
private val _updateStatus = MutableLiveData<Result<Int>>()
private val _gsp = MutableLiveData<Result<GroundStationPosition>>().apply {
value = Result.Success(prefsManager.getPosition())
}
val tleSources = repository.getSources()
val allEntries = repository.getAllEntries()
val selectedEntries = repository.getSelectedEntries()
private var calculationJob: Job? = null
private val _satPassList = MutableLiveData<Result<MutableList<SatPass>>>()
fun getPassList(): LiveData<Result<MutableList<SatPass>>> = _satPassList
fun getTransmittersForSat(id: Int) = liveData { emit(repository.getTransmittersByCatNum(id)) }
fun getPassList(): LiveData<Result<MutableList<SatPass>>> = _satPassList
fun getGSP(): LiveData<Result<GroundStationPosition>> = _gsp
fun getCompass() = prefsManager.getCompass()
fun getHoursAhead() = prefsManager.getHoursAhead()
fun getMinElevation() = prefsManager.getMinElevation()
suspend fun getAllEntries() = repository.getAllEntries()
fun setPassPrefs(hoursAhead: Int, minEl: Double) {
prefsManager.setHoursAhead(hoursAhead)
prefsManager.setMinElevation(minEl)
}
fun updatePosition() {
val lastLoc = prefsManager.getLastKnownLocation()
if (lastLoc == null) {
_gsp.postValue(Result.Error(Exception()))
} else {
val gsp = GroundStationPosition(lastLoc.latitude, lastLoc.longitude, lastLoc.altitude)
_gsp.postValue(Result.Success(gsp))
}
prefsManager.updateLocation()
}
fun updateEntriesFromFile(uri: Uri) {
viewModelScope.launch(Dispatchers.IO) {
try {
val selected = repository.getSelectedEntries().map { it.catNum }
repository.updateEntriesFromFile(uri)
repository.updateEntriesSelection(selected)
_updateStatus.postValue(Result.Success(0))
} catch (e: Exception) {
_updateStatus.postValue(Result.Error(e))
}
val selected = selectedEntries.value!!.map { it.catNum }
repository.updateEntriesFromFile(uri)
repository.updateEntriesSelection(selected)
}
}
fun updateSatData(list: List<TleSource>) {
fun updateSatelliteData(list: List<TleSource>) {
viewModelScope.launch(Dispatchers.IO) {
try {
val selected = repository.getSelectedEntries().map { it.catNum }
repository.updateSources(list)
repository.updateEntriesFromUrl(list)
repository.updateTransmitters()
repository.updateEntriesSelection(selected)
_updateStatus.postValue(Result.Success(0))
} catch (e: Exception) {
_updateStatus.postValue(Result.Error(e))
}
val selected = selectedEntries.value!!.map { it.catNum }
repository.updateSources(list)
repository.updateEntriesFromUrl(list)
repository.updateTransmitters()
repository.updateEntriesSelection(selected)
}
}
@@ -114,12 +85,12 @@ class SharedViewModel @Inject constructor(
calculationJob?.cancel()
var passList = mutableListOf<SatPass>()
val dateNow = Date()
val gsp = prefsManager.getPosition()
val gsp = prefsManager.getStationPosition()
calculationJob = viewModelScope.launch(Dispatchers.Default) {
repository.getSelectedEntries().forEach {
repository.getSelectedEntries().value?.forEach {
passList.addAll(getPassesForEntries(it, dateNow, gsp))
}
passList = filterAndSortPasses(passList, dateNow, getHoursAhead())
passList = filterAndSortPasses(passList, dateNow, prefsManager.getHoursAhead())
_satPassList.postValue(Result.Success(passList))
}
}
@@ -136,17 +107,13 @@ class SharedViewModel @Inject constructor(
}
}
fun getTleSources(): List<TleSource> = runBlocking {
return@runBlocking repository.getSources()
}
private fun getPassesForEntries(
entry: SatEntry,
dateNow: Date,
gsp: GroundStationPosition
): MutableList<SatPass> {
val predictor = PassPredictor(entry.tle, gsp)
val passes = predictor.getPasses(dateNow, getHoursAhead(), true)
val passes = predictor.getPasses(dateNow, prefsManager.getHoursAhead(), true)
val passList = passes.map { SatPass(entry.tle, predictor, it) }
return passList as MutableList<SatPass>
}
@@ -163,7 +130,7 @@ class SharedViewModel @Inject constructor(
}
passes.removeAll { it.pass.startTime.after(dateFuture) }
passes.removeAll { it.pass.endTime.before(dateNow) }
passes.removeAll { it.pass.maxEl < getMinElevation() }
passes.removeAll { it.pass.maxEl < prefsManager.getMinElevation() }
passes.sortBy { it.pass.startTime }
return passes
}
@@ -25,10 +25,25 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.rtbishop.look4sat.data.SatEntry
import com.rtbishop.look4sat.databinding.ItemSatEntryBinding
import java.util.*
class EntriesAdapter(private var entries: MutableList<SatEntry>) :
class EntriesAdapter(private var entries: MutableList<SatEntry> = mutableListOf()) :
RecyclerView.Adapter<EntriesAdapter.SatEntryHolder>() {
private var selectAllToggle = true
inner class SatEntryHolder(itemView: View, private val binding: ItemSatEntryBinding) :
RecyclerView.ViewHolder(itemView) {
fun bind(satEntry: SatEntry) {
binding.satEntryCheckbox.text = satEntry.name
binding.satEntryCheckbox.isChecked = satEntry.isSelected
itemView.setOnClickListener {
satEntry.isSelected = binding.satEntryCheckbox.isChecked
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SatEntryHolder {
val binding = ItemSatEntryBinding
.inflate(LayoutInflater.from(parent.context), parent, false)
@@ -43,24 +58,50 @@ class EntriesAdapter(private var entries: MutableList<SatEntry>) :
return entries.size
}
fun getEntries(): MutableList<SatEntry> {
return entries
}
fun setEntries(list: MutableList<SatEntry>) {
entries = list
notifyDataSetChanged()
}
fun getEntries(): MutableList<SatEntry> {
return entries
}
inner class SatEntryHolder(itemView: View, private val binding: ItemSatEntryBinding) :
RecyclerView.ViewHolder(itemView) {
fun bind(satEntry: SatEntry) {
binding.satEntryCheckbox.text = satEntry.name
binding.satEntryCheckbox.isChecked = satEntry.isSelected
itemView.setOnClickListener {
satEntry.isSelected = binding.satEntryCheckbox.isChecked
}
fun selectAll() {
selectAllToggle = if (selectAllToggle) {
val currentList = getEntries()
currentList.forEach { it.isSelected = true }
setEntries(currentList)
false
} else {
val currentList = getEntries()
currentList.forEach { it.isSelected = false }
setEntries(currentList)
true
}
}
fun filterEntries(list: MutableList<SatEntry>, query: String): MutableList<SatEntry> {
if (query.isEmpty()) return list
return try {
filterByCatNum(list, query.toInt())
} catch (e: NumberFormatException) {
filterByName(list, query)
}
}
private fun filterByCatNum(list: MutableList<SatEntry>, catNum: Int): MutableList<SatEntry> {
val filteredList = list.filter { it.catNum == catNum }
return filteredList as MutableList<SatEntry>
}
private fun filterByName(list: MutableList<SatEntry>, query: String): MutableList<SatEntry> {
val searchQuery = query.toLowerCase(Locale.getDefault())
val filteredList = mutableListOf<SatEntry>()
list.forEach {
val entryName = it.name.toLowerCase(Locale.getDefault())
if (entryName.contains(searchQuery)) filteredList.add(it)
}
return filteredList
}
}
@@ -1,138 +0,0 @@
/*
* Look4Sat. Amateur radio and weather satellite tracker and passes predictor for Android.
* Copyright (C) 2019, 2020 Arty Bishop (bishop.arty@gmail.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.rtbishop.look4sat.ui.fragments
import android.app.Dialog
import android.os.Bundle
import android.view.ViewGroup
import android.view.Window
import android.widget.SearchView
import androidx.appcompat.app.AppCompatDialogFragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.rtbishop.look4sat.data.SatEntry
import com.rtbishop.look4sat.databinding.DialogEntriesBinding
import com.rtbishop.look4sat.ui.adapters.EntriesAdapter
import java.util.*
class EntriesDialog(private var entries: MutableList<SatEntry>) :
AppCompatDialogFragment(), SearchView.OnQueryTextListener {
private lateinit var entriesListener: EntriesSubmitListener
private val entryAdapter = EntriesAdapter(entries)
private var selectAllToggle = true
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val binding = DialogEntriesBinding.inflate(requireActivity().layoutInflater)
val satEntryDialog = Dialog(requireActivity()).apply {
window?.requestFeature(Window.FEATURE_NO_TITLE)
setContentView(binding.root)
window?.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
binding.dialogSearch.apply {
setOnQueryTextListener(this@EntriesDialog)
onActionViewExpanded()
clearFocus()
}
binding.dialogRecycler.apply {
layoutManager = LinearLayoutManager(activity)
adapter = entryAdapter
}
binding.dialogBtnPositive.setOnClickListener { onPositiveClicked() }
binding.dialogBtnNegative.setOnClickListener { onNegativeClicked() }
binding.dialogBtnNeutral.setOnClickListener { onNeutralClicked() }
return satEntryDialog
}
fun setEntriesListener(listener: EntriesSubmitListener): EntriesDialog {
entriesListener = listener
return this
}
private fun filterEntries(list: MutableList<SatEntry>, query: String): MutableList<SatEntry> {
if (query.isEmpty()) return list
return try {
filterByCatNum(list, query.toInt())
} catch (e: NumberFormatException) {
filterByName(list, query)
}
}
private fun filterByCatNum(list: MutableList<SatEntry>, catNum: Int): MutableList<SatEntry> {
val filteredList = list.filter { it.catNum == catNum }
return filteredList as MutableList<SatEntry>
}
private fun filterByName(list: MutableList<SatEntry>, query: String): MutableList<SatEntry> {
val searchQuery = query.toLowerCase(Locale.getDefault())
val filteredList = mutableListOf<SatEntry>()
list.forEach {
val name = it.name.toLowerCase(Locale.getDefault())
if (name.contains(searchQuery)) filteredList.add(it)
}
return filteredList
}
private fun onPositiveClicked() {
val catNumList = mutableListOf<Int>().apply {
entries.forEach { if (it.isSelected) this.add(it.catNum) }
}
entriesListener.onEntriesSubmit(catNumList)
dismiss()
}
private fun onNegativeClicked() {
dismiss()
}
private fun onNeutralClicked() {
selectAllToggle = if (selectAllToggle) {
val currentList = entryAdapter.getEntries()
currentList.forEach { it.isSelected = true }
entryAdapter.setEntries(currentList)
false
} else {
val currentList = entryAdapter.getEntries()
currentList.forEach { it.isSelected = false }
entryAdapter.setEntries(currentList)
true
}
}
override fun onQueryTextChange(newText: String): Boolean {
val filteredList = filterEntries(entries, newText)
entryAdapter.setEntries(filteredList)
return false
}
override fun onQueryTextSubmit(query: String): Boolean {
return false
}
interface EntriesSubmitListener {
fun onEntriesSubmit(catNumList: MutableList<Int>)
}
}
@@ -3,18 +3,25 @@ package com.rtbishop.look4sat.ui.fragments
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.SearchView
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.rtbishop.look4sat.Look4SatApp
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.dagger.ViewModelFactory
import com.rtbishop.look4sat.data.SatEntry
import com.rtbishop.look4sat.data.TleSource
import com.rtbishop.look4sat.databinding.FragmentEntriesBinding
import com.rtbishop.look4sat.ui.SharedViewModel
import com.rtbishop.look4sat.ui.adapters.EntriesAdapter
import javax.inject.Inject
class EntriesFragment : Fragment(R.layout.fragment_entries), SourcesDialog.SourcesSubmitListener {
class EntriesFragment : Fragment(R.layout.fragment_entries),
SourcesDialog.SourcesSubmitListener,
SearchView.OnQueryTextListener {
@Inject
lateinit var factory: ViewModelFactory
@@ -22,25 +29,55 @@ class EntriesFragment : Fragment(R.layout.fragment_entries), SourcesDialog.Sourc
private lateinit var binding: FragmentEntriesBinding
private lateinit var viewModel: SharedViewModel
private val pickFileReqCode = 100
private val entriesAdapter = EntriesAdapter()
private var tleSources = listOf<TleSource>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentEntriesBinding.bind(view)
(requireActivity().application as Look4SatApp).appComponent.inject(this)
viewModel = ViewModelProvider(requireActivity(), factory).get(SharedViewModel::class.java)
binding.importWeb.setOnClickListener { showSourcesDialog() }
binding.importFile.setOnClickListener { showFileDialog() }
setupUI()
setupObservers()
}
private fun setupUI() {
binding.apply {
importWeb.setOnClickListener { showSourcesDialog() }
importFile.setOnClickListener { showFileDialog() }
selectAll.setOnClickListener { entriesAdapter.selectAll() }
entriesFab.setOnClickListener { goToPassesAndCalculateForSelection() }
searchBar.setOnQueryTextListener(this@EntriesFragment)
entriesRecycler.layoutManager = LinearLayoutManager(requireActivity())
entriesRecycler.adapter = entriesAdapter
}
}
private fun setupObservers() {
viewModel.tleSources.observe(viewLifecycleOwner, { sources ->
tleSources = sources
})
viewModel.allEntries.observe(viewLifecycleOwner, { entries ->
entriesAdapter.setEntries(entries as MutableList<SatEntry>)
})
}
// Entries update from web
private fun showSourcesDialog() {
val fragmentManager = childFragmentManager
SourcesDialog(viewModel.getTleSources()).apply {
SourcesDialog(tleSources).apply {
setSourcesListener(this@EntriesFragment)
show(fragmentManager, "TleSourcesDialog")
}
}
override fun onSourcesSubmit(list: List<TleSource>) {
viewModel.updateSatelliteData(list)
}
// Entries update from file
private fun showFileDialog() {
Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
@@ -49,13 +86,29 @@ class EntriesFragment : Fragment(R.layout.fragment_entries), SourcesDialog.Sourc
}
}
override fun onSourcesSubmit(list: List<TleSource>) {
viewModel.updateSatData(list)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == pickFileReqCode && resultCode == AppCompatActivity.RESULT_OK) {
data?.data?.also { uri -> viewModel.updateEntriesFromFile(uri) }
} else super.onActivityResult(requestCode, resultCode, data)
}
// Search and select entries
private fun goToPassesAndCalculateForSelection() {
val catNumList = mutableListOf<Int>().apply {
entriesAdapter.getEntries().forEach { if (it.isSelected) this.add(it.catNum) }
}
viewModel.updateEntriesSelection(catNumList)
requireView().findNavController().navigate(R.id.action_entries_to_passes)
}
override fun onQueryTextChange(newText: String): Boolean {
val filteredList = entriesAdapter.filterEntries(entriesAdapter.getEntries(), newText)
entriesAdapter.setEntries(filteredList)
return false
}
override fun onQueryTextSubmit(query: String): Boolean {
return false
}
}
@@ -22,6 +22,7 @@ import com.rtbishop.look4sat.data.SatItem
import com.rtbishop.look4sat.data.SatPass
import com.rtbishop.look4sat.databinding.FragmentMapBinding
import com.rtbishop.look4sat.ui.SharedViewModel
import com.rtbishop.look4sat.utility.PrefsManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -43,6 +44,10 @@ class MapFragment : Fragment(R.layout.fragment_map) {
@Inject
lateinit var modelFactory: ViewModelFactory
@Inject
lateinit var prefsManager: PrefsManager
private lateinit var mainActivity: FragmentActivity
private lateinit var viewModel: SharedViewModel
private lateinit var binding: FragmentMapBinding
@@ -77,6 +82,7 @@ class MapFragment : Fragment(R.layout.fragment_map) {
}
setupMapView()
setupPosOverlay(prefsManager.getStationPosition())
setupObservers()
}
@@ -121,14 +127,6 @@ class MapFragment : Fragment(R.layout.fragment_map) {
}
private fun setupObservers() {
viewModel.getGSP().observe(viewLifecycleOwner, { stationPosition ->
when (stationPosition) {
is Result.Success -> {
setupPosOverlay(stationPosition.data)
}
}
})
viewModel.getPassList().observe(viewLifecycleOwner, { satPasses ->
when (satPasses) {
is Result.Success -> {
@@ -99,7 +99,7 @@ class PassesFragment : Fragment(R.layout.fragment_passes) {
setTimer()
binding.passesFilter.setOnClickListener {
showSatPassPrefsDialog(viewModel.getHoursAhead(), viewModel.getMinElevation())
showSatPassPrefsDialog(prefsManager.getHoursAhead(), prefsManager.getMinElevation())
}
binding.passesFab.setOnClickListener {
viewModel.calculatePasses()
@@ -128,7 +128,8 @@ class PassesFragment : Fragment(R.layout.fragment_passes) {
getString(R.string.pref_min_el_input_error).snack(requireView())
}
else -> {
viewModel.setPassPrefs(hours, elevation)
prefsManager.setHoursAhead(hours)
prefsManager.setMinElevation(elevation)
viewModel.calculatePasses()
}
}
@@ -38,6 +38,7 @@ import com.rtbishop.look4sat.databinding.FragmentPolarBinding
import com.rtbishop.look4sat.ui.SharedViewModel
import com.rtbishop.look4sat.ui.adapters.TransAdapter
import com.rtbishop.look4sat.ui.views.PolarView
import com.rtbishop.look4sat.utility.PrefsManager
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.*
@@ -48,6 +49,10 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
@Inject
lateinit var modelFactory: ViewModelFactory
@Inject
lateinit var prefsManager: PrefsManager
private lateinit var mainActivity: FragmentActivity
private lateinit var viewModel: SharedViewModel
private lateinit var binding: FragmentPolarBinding
@@ -69,13 +74,13 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
layoutManager = LinearLayoutManager(mainActivity)
adapter = transmitterAdapter
}
calculateMagneticDeclination()
observePasses()
observeStationPosition()
}
override fun onResume() {
super.onResume()
if (viewModel.getCompass()) {
if (prefsManager.getCompass()) {
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR).also { sensor ->
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL)
}
@@ -84,7 +89,7 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
override fun onPause() {
super.onPause()
if (viewModel.getCompass()) {
if (prefsManager.getCompass()) {
sensorManager.unregisterListener(this)
}
}
@@ -132,18 +137,15 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
})
}
private fun observeStationPosition() {
viewModel.getGSP().observe(viewLifecycleOwner, { result ->
if (result is Result.Success) {
val geoField = GeomagneticField(
result.data.latitude.toFloat(),
result.data.longitude.toFloat(),
result.data.heightAMSL.toFloat(),
System.currentTimeMillis()
)
magneticDeclination = geoField.declination
}
})
private fun calculateMagneticDeclination() {
val position = prefsManager.getStationPosition()
val geoField = GeomagneticField(
position.latitude.toFloat(),
position.longitude.toFloat(),
position.heightAMSL.toFloat(),
System.currentTimeMillis()
)
magneticDeclination = geoField.declination
}
private fun refreshText() {
@@ -20,7 +20,6 @@
package com.rtbishop.look4sat.utility
import android.content.SharedPreferences
import android.location.Location
import android.location.LocationManager
import androidx.core.content.edit
import com.github.amsacode.predict4java.GroundStationPosition
@@ -72,21 +71,19 @@ class PrefsManager @Inject constructor(
return preferences.getBoolean(keyCompass, true)
}
fun getPosition(): GroundStationPosition {
fun getStationPosition(): GroundStationPosition {
val lat = preferences.getString(keyLatitude, defaultGSP)!!.toDouble()
val lon = preferences.getString(keyLongitude, defaultGSP)!!.toDouble()
val alt = preferences.getString(keyAltitude, defaultGSP)!!.toDouble()
return GroundStationPosition(lat, lon, alt)
}
fun getLastKnownLocation(): Location? {
val provPassive = LocationManager.PASSIVE_PROVIDER
return try {
val location = locationManager.getLastKnownLocation(provPassive)
location?.let {
val lat = location.latitude.round(4)
val lon = location.longitude.round(4)
val alt = location.altitude.round(1)
fun updateLocation() {
try {
locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER)?.let {
val lat = it.latitude.round(4)
val lon = it.longitude.round(4)
val alt = it.altitude.round(1)
preferences.edit {
putString(keyLatitude, lat.toString())
putString(keyLongitude, lon.toString())
@@ -94,9 +91,7 @@ class PrefsManager @Inject constructor(
apply()
}
}
location
} catch (e: SecurityException) {
null
}
}
+11 -3
View File
@@ -26,7 +26,15 @@
<fragment
android:id="@+id/nav_entries"
android:name="com.rtbishop.look4sat.ui.fragments.EntriesFragment"
tools:layout="@layout/fragment_entries" />
tools:layout="@layout/fragment_entries">
<action
android:id="@+id/action_entries_to_passes"
app:destination="@id/nav_passes"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
</fragment>
<fragment
android:id="@+id/nav_passes"
@@ -37,8 +45,8 @@
app:destination="@id/nav_polar"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim" />
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
</fragment>
<fragment
-1
View File
@@ -22,7 +22,6 @@ buildscript {
gradle_version = '4.0.1'
gradle_plugin_version = '1.4.10'
material_version = '1.2.1'
app_compat_version = '1.2.0'
constraint_layout_version = '2.0.1'
ktx_version = '1.3.1'
preference_version = '1.1.1'