diff --git a/app/src/main/java/com/rtbishop/look4sat/data/PassPrefs.kt b/app/src/main/java/com/rtbishop/look4sat/data/PassPrefs.kt new file mode 100644 index 00000000..6ae6b9b9 --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/data/PassPrefs.kt @@ -0,0 +1,3 @@ +package com.rtbishop.look4sat.data + +data class PassPrefs(val hoursAhead: Int, val minEl: Double) \ No newline at end of file diff --git a/app/src/main/java/com/rtbishop/look4sat/repo/DefaultRepository.kt b/app/src/main/java/com/rtbishop/look4sat/repo/DefaultRepository.kt index 81e4ba1d..939d4864 100644 --- a/app/src/main/java/com/rtbishop/look4sat/repo/DefaultRepository.kt +++ b/app/src/main/java/com/rtbishop/look4sat/repo/DefaultRepository.kt @@ -78,18 +78,8 @@ class DefaultRepository @Inject constructor( override suspend fun updateEntriesFromUrl(urlList: List) { withContext(Dispatchers.IO) { - val streams = mutableListOf() - 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() - 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): MutableList { + val streams = mutableListOf() + 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): MutableList { + val entries = mutableListOf() + streams.forEach { + val list = TLE.importSat(it).map { tle -> SatEntry(tle) } + entries.addAll(list) + } + return entries + } + //////////////////////////////////////////////////////////////////////////////////////////////// override suspend fun updateTransmitters() { diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt index ce3bcc7d..02232dc8 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt @@ -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>>() fun getPassList(): LiveData>> = _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 { 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 } @@ -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 } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/adapters/PassesAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/ui/adapters/PassesAdapter.kt index 685f7c6b..370195fd 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/adapters/PassesAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/adapters/PassesAdapter.kt @@ -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, - private val prefsManager: PrefsManager -) : +class PassesAdapter(private var satPassList: MutableList = mutableListOf()) : RecyclerView.Adapter() { + private var shouldUseUTC: Boolean = false + + fun setShouldUseUTC(boolean: Boolean) { + shouldUseUTC = boolean + } + fun setList(list: MutableList) { 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) diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/fragments/MapFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/fragments/MapFragment.kt index 8382be29..cf8a1506 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/fragments/MapFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/fragments/MapFragment.kt @@ -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() } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/fragments/PassesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/fragments/PassesFragment.kt index b0814372..7cc9388d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/fragments/PassesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/fragments/PassesFragment.kt @@ -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() 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() } } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/fragments/PolarFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/fragments/PolarFragment.kt index 816f2508..7a9c1126 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/fragments/PolarFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/fragments/PolarFragment.kt @@ -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(), diff --git a/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt b/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt index 141c859b..57927987 100644 --- a/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt +++ b/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt @@ -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 } } diff --git a/app/src/main/java/com/rtbishop/look4sat/utility/Utilities.kt b/app/src/main/java/com/rtbishop/look4sat/utility/Utilities.kt index 837157ae..77d4d6be 100644 --- a/app/src/main/java/com/rtbishop/look4sat/utility/Utilities.kt +++ b/app/src/main/java/com/rtbishop/look4sat/utility/Utilities.kt @@ -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())) } } \ No newline at end of file