From 89299d1c3b5703b14c7ef2f663c53a81e25ab744 Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Fri, 29 Nov 2019 11:01:51 +0000 Subject: [PATCH] Further refactoring, showing passes now after the radarFragment onBack pressed. Trying to decide on the way it all should work. --- .../com/rtbishop/lookingsat/MainViewModel.kt | 98 +++++++++---------- .../com/rtbishop/lookingsat/ui/SkyFragment.kt | 59 ++++------- 2 files changed, 62 insertions(+), 95 deletions(-) diff --git a/app/src/main/java/com/rtbishop/lookingsat/MainViewModel.kt b/app/src/main/java/com/rtbishop/lookingsat/MainViewModel.kt index 9d83b006..5d19a1ad 100644 --- a/app/src/main/java/com/rtbishop/lookingsat/MainViewModel.kt +++ b/app/src/main/java/com/rtbishop/lookingsat/MainViewModel.kt @@ -4,10 +4,8 @@ import android.app.Application import android.content.Context import android.content.SharedPreferences import android.location.Location -import android.util.Log import androidx.core.content.edit import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import androidx.preference.PreferenceManager @@ -29,95 +27,86 @@ import javax.inject.Inject class MainViewModel(application: Application) : AndroidViewModel(application) { - private val keyLat = "LATITUDE" - private val keyLon = "LONGITUDE" - private val keyHeight = "HEIGHT" - private val tleFile = "tles.txt" - private val tag = "myTag" + private val keyLat = "latitude" + private val keyLon = "longitude" + private val keyHeight = "height" + private val keyHours = "hoursAhead" + private val keyMaxEl = "maxElevation" + private val tleFileName = "tleFile.txt" + private val preferences = PreferenceManager.getDefaultSharedPreferences(application) + private val locationClient = LocationServices.getFusedLocationProviderClient(application) + + val debugMessage = MutableLiveData("") @Inject lateinit var repository: Repository - private val preferences = PreferenceManager.getDefaultSharedPreferences(application) - private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(application) - init { (application as LookingSatApp).appComponent.inject(this) } - private val _debugMessage = MutableLiveData("") - val debugMessage: LiveData = _debugMessage - - private val _tleMainList = MutableLiveData>(loadTwoLineElementFile()) - val tleMainList: LiveData> = _tleMainList - - private val _tleSelectedMap = MutableLiveData>(mutableMapOf()) - val tleSelectedMap: LiveData> = _tleSelectedMap - - private val _satPassPrefs = MutableLiveData( - SatPassPrefs( - preferences.getInt("hoursAhead", 8), - preferences.getDouble("maxEl", 20.0) - ) - ) - val satPassPrefs: LiveData = _satPassPrefs - - private val _gsp = MutableLiveData( + val gsp = MutableLiveData( GroundStationPosition( preferences.getDouble(keyLat, 0.0), preferences.getDouble(keyLon, 0.0), preferences.getDouble(keyHeight, 0.0) ) ) - val gsp: LiveData = _gsp + + var tleMainList = loadTwoLineElementFile() + var tleSelectedMap = mutableMapOf() + var passPrefs = SatPassPrefs( + preferences.getInt(keyHours, 8), + preferences.getDouble(keyMaxEl, 16.0) + ) private fun loadTwoLineElementFile(): List { return try { - TLE.importSat(getApplication().openFileInput(tleFile)) + TLE.importSat(getApplication().openFileInput(tleFileName)) .sortedWith(compareBy { it.name }) } catch (exception: FileNotFoundException) { - _debugMessage.postValue("TLE file wasn't found") + debugMessage.postValue("TLE file wasn't found") emptyList() } } - suspend fun getPasses(satMap: Map, hours: Int, maxEl: Double): List { + suspend fun getPasses(): List { val satPassList = mutableListOf() withContext(Dispatchers.Default) { - satMap.forEach { (tle, value) -> + tleSelectedMap.forEach { (tle, value) -> if (value) { try { - val passPredictor = PassPredictor(tle, gsp.value) - val passes = passPredictor.getPasses(Date(), hours, false) - passes.forEach { satPassList.add(SatPass(tle, passPredictor, it)) } + val predictor = PassPredictor(tle, gsp.value) + val passes = predictor.getPasses(Date(), passPrefs.hoursAhead, false) + passes.forEach { satPassList.add(SatPass(tle, predictor, it)) } } catch (exception: IllegalArgumentException) { - Log.d(tag, "There was a problem with TLE") + debugMessage.postValue("There was a problem with TLE") } catch (exception: SatNotFoundException) { - Log.d(tag, "Certain satellites shall not pass") + debugMessage.postValue("Certain satellites shall not pass") } } } - satPassList.retainAll { it.pass.maxEl >= maxEl } + satPassList.retainAll { it.pass.maxEl >= passPrefs.maxEl } satPassList.sortBy { it.pass.startTime } } return satPassList } fun updateSelectedSatMap(mutableMap: MutableMap) { - _tleSelectedMap.postValue(mutableMap) + tleSelectedMap = mutableMap } fun updatePassPrefs(hoursAhead: Int, maxEl: Double) { - _satPassPrefs.postValue(SatPassPrefs(hoursAhead, maxEl)) + passPrefs = SatPassPrefs(hoursAhead, maxEl) preferences.edit { - putInt("hoursAhead", hoursAhead) - putDouble("maxEl", maxEl) + putInt(keyHours, hoursAhead) + putDouble(keyMaxEl, maxEl) apply() } } fun updateLocation() { - fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? -> + locationClient.lastLocation.addOnSuccessListener { location: Location? -> val lat = location?.latitude ?: 0.0 val lon = location?.longitude ?: 0.0 val height = location?.altitude ?: 0.0 @@ -128,8 +117,8 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { putDouble(keyHeight, height) apply() } - _gsp.postValue(GroundStationPosition(lat, lon, height)) - _debugMessage.postValue("Location was updated") + gsp.postValue(GroundStationPosition(lat, lon, height)) + debugMessage.postValue("Location was updated") } } @@ -137,13 +126,14 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { viewModelScope.launch(Dispatchers.IO) { try { val stream = repository.fetchTleStream() - getApplication().openFileOutput(tleFile, Context.MODE_PRIVATE).use { - it.write(stream.readBytes()) - } - _tleMainList.postValue(loadTwoLineElementFile()) - _debugMessage.postValue("TLE file was updated") + getApplication().openFileOutput(tleFileName, Context.MODE_PRIVATE) + .use { + it.write(stream.readBytes()) + } + tleMainList = loadTwoLineElementFile() + debugMessage.postValue("TLE file was updated") } catch (exception: IOException) { - _debugMessage.postValue("Couldn't update TLE file") + debugMessage.postValue("Couldn't update TLE file") } } } @@ -152,9 +142,9 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { viewModelScope.launch(Dispatchers.IO) { try { repository.updateTransmittersDatabase() - _debugMessage.postValue("Transmitters were updated") + debugMessage.postValue("Transmitters were updated") } catch (exception: IOException) { - _debugMessage.postValue("Couldn't update transmitters") + debugMessage.postValue("Couldn't update transmitters") } } } diff --git a/app/src/main/java/com/rtbishop/lookingsat/ui/SkyFragment.kt b/app/src/main/java/com/rtbishop/lookingsat/ui/SkyFragment.kt index e4065e5c..714681ba 100644 --- a/app/src/main/java/com/rtbishop/lookingsat/ui/SkyFragment.kt +++ b/app/src/main/java/com/rtbishop/lookingsat/ui/SkyFragment.kt @@ -17,8 +17,6 @@ import com.github.amsacode.predict4java.TLE import com.google.android.material.floatingactionbutton.FloatingActionButton import com.rtbishop.lookingsat.MainViewModel import com.rtbishop.lookingsat.R -import com.rtbishop.lookingsat.repo.SatPass -import com.rtbishop.lookingsat.repo.SatPassPrefs import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.util.concurrent.TimeUnit @@ -34,12 +32,14 @@ class SkyFragment : Fragment() { private lateinit var btnPassPrefs: ImageButton private lateinit var progressBar: ProgressBar private lateinit var fab: FloatingActionButton - private lateinit var tleMainList: List - private var selectedSatMap: MutableMap = mutableMapOf() - private lateinit var satPassPrefs: SatPassPrefs private lateinit var aosTimer: CountDownTimer private var isTimerSet: Boolean = false + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { @@ -49,12 +49,9 @@ class SkyFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupViews(view) - setupObservers() - resetTimer() } private fun setupViews(view: View) { - viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java) timeToAos = (activity as MainActivity).findViewById(R.id.toolbar_time_to_aos) btnPassPrefs = (activity as MainActivity).findViewById(R.id.toolbar_btn_refresh) progressBar = view.findViewById(R.id.sky_progressbar) @@ -66,29 +63,7 @@ class SkyFragment : Fragment() { btnPassPrefs.setOnClickListener { showSatPassPrefsDialog() } fab.setOnClickListener { showSelectSatDialog() } - satPassPrefs = viewModel.satPassPrefs.value ?: SatPassPrefs(8, 20.0) - } - - private fun setupObservers() { - viewModel.tleMainList.observe(this, Observer { - tleMainList = it - selectedSatMap.clear() - viewModel.updateSelectedSatMap(selectedSatMap) - }) - - viewModel.tleSelectedMap.observe(this, Observer { - selectedSatMap = it - calculatePasses() - }) - - viewModel.satPassPrefs.observe(this, Observer { - satPassPrefs = it - calculatePasses() - }) - - viewModel.gsp.observe(this, Observer { - calculatePasses() - }) + viewModel.gsp.observe(this, Observer { calculatePasses() }) } private fun showSatPassPrefsDialog() { @@ -96,8 +71,8 @@ class SkyFragment : Fragment() { val satPassPrefView = View.inflate(context, R.layout.sat_pass_pref, null) val etHours = satPassPrefView.findViewById(R.id.pass_pref_et_hours) val etMaxEl = satPassPrefView.findViewById(R.id.pass_pref_et_maxEl) - etHours.setText(viewModel.satPassPrefs.value?.hoursAhead.toString()) - etMaxEl.setText(viewModel.satPassPrefs.value?.maxEl.toString()) + etHours.setText(viewModel.passPrefs.hoursAhead.toString()) + etMaxEl.setText(viewModel.passPrefs.maxEl.toString()) val builder = AlertDialog.Builder(context) builder.setTitle(getString(R.string.title_pass_pref)) @@ -105,6 +80,7 @@ class SkyFragment : Fragment() { val hoursAhead = etHours.text.toString().toInt() val maxEl = etMaxEl.text.toString().toDouble() viewModel.updatePassPrefs(hoursAhead, maxEl) + calculatePasses() } .setNegativeButton(getString(R.string.btn_cancel)) { dialog, _ -> dialog.cancel() @@ -115,10 +91,11 @@ class SkyFragment : Fragment() { } private fun showSelectSatDialog() { + val tleMainList: List = viewModel.tleMainList val tleNameArray = arrayOfNulls(tleMainList.size) val tleCheckedArray = BooleanArray(tleMainList.size) - val builder = AlertDialog.Builder(activity as MainActivity) - val selectionMap = mutableMapOf() + val selectedSatMap = viewModel.tleSelectedMap + val currentSelectionMap = mutableMapOf() if (selectedSatMap.isEmpty()) { tleMainList.withIndex().forEach { (position, tle) -> @@ -132,14 +109,16 @@ class SkyFragment : Fragment() { } } + val builder = AlertDialog.Builder(activity as MainActivity) builder.setTitle(getString(R.string.title_select_sat)) .setMultiChoiceItems(tleNameArray, tleCheckedArray) { _, which, isChecked -> - selectionMap[tleMainList[which]] = isChecked + currentSelectionMap[tleMainList[which]] = isChecked } .setPositiveButton(getString(R.string.btn_ok)) { _, _ -> - for ((tle, value) in selectionMap) { + for ((tle, value) in currentSelectionMap) { selectedSatMap[tle] = value viewModel.updateSelectedSatMap(selectedSatMap) + calculatePasses() } } .setNegativeButton(getString(R.string.btn_cancel)) { dialog, _ -> @@ -148,20 +127,18 @@ class SkyFragment : Fragment() { .setNeutralButton(getString(R.string.btn_clear)) { _, _ -> selectedSatMap.clear() viewModel.updateSelectedSatMap(selectedSatMap) + calculatePasses() } .create() .show() } private fun calculatePasses() { - val hoursAhead = satPassPrefs.hoursAhead - val maxEl = satPassPrefs.maxEl - var satPassList: List lifecycleScope.launch(Dispatchers.Main) { recViewFuture.visibility = View.INVISIBLE progressBar.visibility = View.VISIBLE progressBar.isIndeterminate = true - satPassList = viewModel.getPasses(selectedSatMap, hoursAhead, maxEl) + val satPassList = viewModel.getPasses() recAdapterFuture = SatPassAdapter(satPassList) recViewFuture.adapter = recAdapterFuture progressBar.isIndeterminate = false