Added PassPrefs object, cleaned up the code in SharedViewModel and PrefsManager

pull/49/head
Arty Bishop 2020-09-27 16:05:23 +01:00
rodzic 6b39a6759a
commit 8164384498
9 zmienionych plików z 128 dodań i 111 usunięć

Wyświetl plik

@ -0,0 +1,3 @@
package com.rtbishop.look4sat.data
data class PassPrefs(val hoursAhead: Int, val minEl: Double)

Wyświetl plik

@ -78,18 +78,8 @@ class DefaultRepository @Inject constructor(
override suspend fun updateEntriesFromUrl(urlList: List<TleSource>) {
withContext(Dispatchers.IO) {
val streams = mutableListOf<InputStream>()
urlList.withIndex().forEach {
val request = Request.Builder().url(it.value.url).build()
val stream = client.newCall(request).execute().body?.byteStream()
stream?.let { inputStream -> streams.add(inputStream) }
}
val entries = mutableListOf<SatEntry>()
streams.forEach {
val list = TLE.importSat(it).map { tle -> SatEntry(tle) }
entries.addAll(list)
}
val streams = getStreamsForSources(urlList)
val entries = getEntriesForStreams(streams)
entriesDao.clearEntries()
entriesDao.insertEntries(entries)
}
@ -100,6 +90,25 @@ class DefaultRepository @Inject constructor(
catNumList.forEach { entriesDao.updateEntrySelection(it) }
}
private fun getStreamsForSources(urlList: List<TleSource>): MutableList<InputStream> {
val streams = mutableListOf<InputStream>()
urlList.withIndex().forEach {
val request = Request.Builder().url(it.value.url).build()
val stream = client.newCall(request).execute().body?.byteStream()
stream?.let { inputStream -> streams.add(inputStream) }
}
return streams
}
private fun getEntriesForStreams(streams: MutableList<InputStream>): MutableList<SatEntry> {
val entries = mutableListOf<SatEntry>()
streams.forEach {
val list = TLE.importSat(it).map { tle -> SatEntry(tle) }
entries.addAll(list)
}
return entries
}
////////////////////////////////////////////////////////////////////////////////////////////////
override suspend fun updateTransmitters() {

Wyświetl plik

@ -22,10 +22,7 @@ package com.rtbishop.look4sat.ui
import android.net.Uri
import androidx.lifecycle.*
import com.github.amsacode.predict4java.GroundStationPosition
import com.rtbishop.look4sat.data.Result
import com.rtbishop.look4sat.data.SatEntry
import com.rtbishop.look4sat.data.SatPass
import com.rtbishop.look4sat.data.TleSource
import com.rtbishop.look4sat.data.*
import com.rtbishop.look4sat.repo.Repository
import com.rtbishop.look4sat.utility.PassPredictor
import com.rtbishop.look4sat.utility.PrefsManager
@ -49,10 +46,30 @@ class SharedViewModel @Inject constructor(
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 updatePosition() {
prefsManager.updateLocation()
fun getPassPrefs(): PassPrefs {
return prefsManager.getPassPrefs()
}
fun setPassPrefs(hoursAhead: Int, minEl: Double) {
prefsManager.setPassPrefs(hoursAhead, minEl)
}
fun getStationPosition(): GroundStationPosition {
return prefsManager.getStationPosition()
}
fun updateStationPosition() {
prefsManager.updateStationPosition()
}
fun shouldUseUTC(): Boolean {
return prefsManager.shouldUseUTC()
}
fun shouldUseCompass(): Boolean {
return prefsManager.shouldUseCompass()
}
fun updateEntriesFromFile(uri: Uri) {
@ -90,7 +107,8 @@ class SharedViewModel @Inject constructor(
repository.getSelectedEntries().value?.forEach {
passList.addAll(getPassesForEntries(it, dateNow, gsp))
}
passList = filterAndSortPasses(passList, dateNow, prefsManager.getHoursAhead())
val hoursAhead = prefsManager.getPassPrefs().hoursAhead
passList = filterAndSortPasses(passList, dateNow, hoursAhead)
_satPassList.postValue(Result.Success(passList))
}
}
@ -113,7 +131,8 @@ class SharedViewModel @Inject constructor(
gsp: GroundStationPosition
): MutableList<SatPass> {
val predictor = PassPredictor(entry.tle, gsp)
val passes = predictor.getPasses(dateNow, prefsManager.getHoursAhead(), true)
val hoursAhead = prefsManager.getPassPrefs().hoursAhead
val passes = predictor.getPasses(dateNow, hoursAhead, true)
val passList = passes.map { SatPass(entry.tle, predictor, it) }
return passList as MutableList<SatPass>
}
@ -128,9 +147,10 @@ class SharedViewModel @Inject constructor(
it.add(Calendar.HOUR, hoursAhead)
it.time
}
val minEl = prefsManager.getPassPrefs().minEl
passes.removeAll { it.pass.startTime.after(dateFuture) }
passes.removeAll { it.pass.endTime.before(dateNow) }
passes.removeAll { it.pass.maxEl < prefsManager.getMinElevation() }
passes.removeAll { it.pass.maxEl < minEl }
passes.sortBy { it.pass.startTime }
return passes
}

Wyświetl plik

@ -30,16 +30,18 @@ import com.rtbishop.look4sat.data.SatPass
import com.rtbishop.look4sat.databinding.ItemPassGeoBinding
import com.rtbishop.look4sat.databinding.ItemPassLeoBinding
import com.rtbishop.look4sat.ui.fragments.PassesFragmentDirections
import com.rtbishop.look4sat.utility.PrefsManager
import java.text.SimpleDateFormat
import java.util.*
class PassesAdapter(
private var satPassList: MutableList<SatPass>,
private val prefsManager: PrefsManager
) :
class PassesAdapter(private var satPassList: MutableList<SatPass> = mutableListOf()) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var shouldUseUTC: Boolean = false
fun setShouldUseUTC(boolean: Boolean) {
shouldUseUTC = boolean
}
fun setList(list: MutableList<SatPass>) {
satPassList = list
notifyDataSetChanged()
@ -119,7 +121,7 @@ class PassesAdapter(
val dateFormat =
SimpleDateFormat(context.getString(R.string.pass_dateTime), Locale.getDefault())
if (prefsManager.isTimeUTC()) dateFormat.timeZone = TimeZone.getTimeZone("UTC")
if (shouldUseUTC) dateFormat.timeZone = TimeZone.getTimeZone("UTC")
binding.passLeoAosTime.text = dateFormat.format(satPass.pass.startTime)
binding.passLeoLosTime.text = dateFormat.format(satPass.pass.endTime)

Wyświetl plik

@ -22,7 +22,6 @@ 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
@ -45,9 +44,6 @@ 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
@ -82,7 +78,7 @@ class MapFragment : Fragment(R.layout.fragment_map) {
}
setupMapView()
setupPosOverlay(prefsManager.getStationPosition())
setupPosOverlay(viewModel.getStationPosition())
setupObservers()
}

Wyświetl plik

@ -36,7 +36,6 @@ import com.rtbishop.look4sat.data.SatPass
import com.rtbishop.look4sat.databinding.FragmentPassesBinding
import com.rtbishop.look4sat.ui.SharedViewModel
import com.rtbishop.look4sat.ui.adapters.PassesAdapter
import com.rtbishop.look4sat.utility.PrefsManager
import com.rtbishop.look4sat.utility.Utilities
import com.rtbishop.look4sat.utility.Utilities.snack
import java.util.*
@ -47,14 +46,11 @@ class PassesFragment : Fragment(R.layout.fragment_passes) {
@Inject
lateinit var factory: ViewModelFactory
@Inject
lateinit var prefsManager: PrefsManager
private lateinit var viewModel: SharedViewModel
private lateinit var passesAdapter: PassesAdapter
private lateinit var aosTimer: CountDownTimer
private lateinit var binding: FragmentPassesBinding
private var isTimerSet: Boolean = false
private val passesAdapter = PassesAdapter()
private var satPassList = mutableListOf<SatPass>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -62,7 +58,6 @@ class PassesFragment : Fragment(R.layout.fragment_passes) {
binding = FragmentPassesBinding.bind(view)
(requireActivity().application as Look4SatApp).appComponent.inject(this)
viewModel = ViewModelProvider(requireActivity(), factory).get(SharedViewModel::class.java)
passesAdapter = PassesAdapter(satPassList, prefsManager)
setupObservers()
setupComponents()
}
@ -89,21 +84,22 @@ class PassesFragment : Fragment(R.layout.fragment_passes) {
}
private fun setupComponents() {
binding.passesRecycler.apply {
layoutManager = LinearLayoutManager(requireContext())
adapter = passesAdapter
isVerticalScrollBarEnabled = false
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
binding.apply {
passesRecycler.apply {
layoutManager = LinearLayoutManager(requireContext())
adapter = passesAdapter
isVerticalScrollBarEnabled = false
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
}
passesFilter.setOnClickListener {
val passPrefs = viewModel.getPassPrefs()
showSatPassPrefsDialog(passPrefs.hoursAhead, passPrefs.minEl)
}
passesFab.setOnClickListener { viewModel.calculatePasses() }
}
passesAdapter.setShouldUseUTC(viewModel.shouldUseUTC())
passesAdapter.setList(satPassList)
setTimer()
binding.passesFilter.setOnClickListener {
showSatPassPrefsDialog(prefsManager.getHoursAhead(), prefsManager.getMinElevation())
}
binding.passesFab.setOnClickListener {
viewModel.calculatePasses()
}
}
private fun showSatPassPrefsDialog(hoursAhead: Int, minEl: Double) {
@ -115,11 +111,11 @@ class PassesFragment : Fragment(R.layout.fragment_passes) {
AlertDialog.Builder(requireContext()).apply {
setPositiveButton(getString(android.R.string.ok)) { _, _ ->
val hoursStr = etHoursAhead.text.toString()
val elevationStr = etMinEl.text.toString()
if (hoursStr.isNotEmpty() && elevationStr.isNotEmpty()) {
val hours = hoursStr.toInt()
val elevation = elevationStr.toDouble()
val hoursString = etHoursAhead.text.toString()
val minElString = etMinEl.text.toString()
if (hoursString.isNotEmpty() && minElString.isNotEmpty()) {
val hours = hoursString.toInt()
val elevation = minElString.toDouble()
when {
hours < 1 || hours > 168 -> {
getString(R.string.pref_hours_ahead_input_error).snack(requireView())
@ -128,8 +124,7 @@ class PassesFragment : Fragment(R.layout.fragment_passes) {
getString(R.string.pref_min_el_input_error).snack(requireView())
}
else -> {
prefsManager.setHoursAhead(hours)
prefsManager.setMinElevation(elevation)
viewModel.setPassPrefs(hours, elevation)
viewModel.calculatePasses()
}
}

Wyświetl plik

@ -38,7 +38,6 @@ 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.*
@ -50,9 +49,6 @@ 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
@ -80,7 +76,7 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
override fun onResume() {
super.onResume()
if (prefsManager.getCompass()) {
if (viewModel.shouldUseCompass()) {
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR).also { sensor ->
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL)
}
@ -89,7 +85,7 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
override fun onPause() {
super.onPause()
if (prefsManager.getCompass()) {
if (viewModel.shouldUseCompass()) {
sensorManager.unregisterListener(this)
}
}
@ -138,7 +134,7 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
}
private fun calculateMagneticDeclination() {
val position = prefsManager.getStationPosition()
val position = viewModel.getStationPosition()
val geoField = GeomagneticField(
position.latitude.toFloat(),
position.longitude.toFloat(),

Wyświetl plik

@ -23,6 +23,9 @@ import android.content.SharedPreferences
import android.location.LocationManager
import androidx.core.content.edit
import com.github.amsacode.predict4java.GroundStationPosition
import com.rtbishop.look4sat.data.PassPrefs
import com.rtbishop.look4sat.utility.Utilities.getDouble
import com.rtbishop.look4sat.utility.Utilities.putDouble
import com.rtbishop.look4sat.utility.Utilities.round
import javax.inject.Inject
@ -44,31 +47,18 @@ class PrefsManager @Inject constructor(
const val keyIsFirstLaunch = "keyIsFirstLaunch"
}
fun isFirstLaunch(): Boolean {
val isFirstLaunch = preferences.getBoolean(keyIsFirstLaunch, true)
return if (isFirstLaunch) {
preferences.edit {
putBoolean(keyIsFirstLaunch, false)
apply()
}
true
} else isFirstLaunch
fun getPassPrefs(): PassPrefs {
val hoursAhead = preferences.getInt(keyHoursAhead, defaultHoursAhead)
val minEl = preferences.getDouble(keyMinElevation, defaultMinEl)
return PassPrefs(hoursAhead, minEl)
}
fun isTimeUTC(): Boolean {
return preferences.getBoolean(keyTimeUtc, false)
}
fun getHoursAhead(): Int {
return preferences.getInt(keyHoursAhead, defaultHoursAhead)
}
fun getMinElevation(): Double {
return preferences.getDouble(keyMinElevation, defaultMinEl)
}
fun getCompass(): Boolean {
return preferences.getBoolean(keyCompass, true)
fun setPassPrefs(hoursAhead: Int, minEl: Double) {
preferences.edit {
putInt(keyHoursAhead, hoursAhead)
putDouble(keyMinElevation, minEl)
apply()
}
}
fun getStationPosition(): GroundStationPosition {
@ -78,7 +68,7 @@ class PrefsManager @Inject constructor(
return GroundStationPosition(lat, lon, alt)
}
fun updateLocation() {
fun updateStationPosition() {
try {
locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER)?.let {
val lat = it.latitude.round(4)
@ -95,25 +85,22 @@ class PrefsManager @Inject constructor(
}
}
fun setHoursAhead(hours: Int) {
preferences.edit {
putInt(keyHoursAhead, hours)
apply()
}
fun shouldUseUTC(): Boolean {
return preferences.getBoolean(keyTimeUtc, false)
}
fun setMinElevation(minEl: Double) {
preferences.edit {
putDouble(keyMinElevation, minEl)
apply()
}
fun shouldUseCompass(): Boolean {
return preferences.getBoolean(keyCompass, true)
}
private fun SharedPreferences.Editor.putDouble(key: String, double: Double) {
putLong(key, double.toRawBits())
}
private fun SharedPreferences.getDouble(key: String, default: Double): Double {
return Double.fromBits(getLong(key, default.toRawBits()))
fun isFirstLaunch(): Boolean {
val isFirstLaunch = preferences.getBoolean(keyIsFirstLaunch, true)
return if (isFirstLaunch) {
preferences.edit {
putBoolean(keyIsFirstLaunch, false)
apply()
}
isFirstLaunch
} else isFirstLaunch
}
}

Wyświetl plik

@ -1,5 +1,6 @@
package com.rtbishop.look4sat.utility
import android.content.SharedPreferences
import android.view.View
import com.google.android.material.snackbar.Snackbar
import java.util.concurrent.TimeUnit
@ -7,6 +8,14 @@ import kotlin.math.round
object Utilities {
fun formatForTimer(millis: Long): String {
val format = "%02d:%02d:%02d"
val hours = TimeUnit.MILLISECONDS.toHours(millis) % 60
val minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60
val seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60
return String.format(format, hours, minutes, seconds)
}
fun String.snack(view: View) {
Snackbar.make(view, this, Snackbar.LENGTH_SHORT).show()
}
@ -17,11 +26,11 @@ object Utilities {
return round(this * multiplier) / multiplier
}
fun formatForTimer(millis: Long): String {
val format = "%02d:%02d:%02d"
val hours = TimeUnit.MILLISECONDS.toHours(millis) % 60
val minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60
val seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60
return String.format(format, hours, minutes, seconds)
fun SharedPreferences.Editor.putDouble(key: String, double: Double) {
putLong(key, double.toRawBits())
}
fun SharedPreferences.getDouble(key: String, default: Double): Double {
return Double.fromBits(getLong(key, default.toRawBits()))
}
}