mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Added PassPrefs object, cleaned up the code in SharedViewModel and PrefsManager
This commit is contained in:
1 parent
6b39a6759a
commit
8164384498
9 files changed
+128
-111
No files matched your search
@@ -0,0 +1,3 @@
|
||||
package com.rtbishop.look4sat.data
|
||||
|
||||
data class PassPrefs(val hoursAhead: Int, val minEl: Double)
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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()))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user