Repositories refactoring and merge

This commit is contained in:
Arty Bishop committed 2021-05-16 19:13:10 +01:00
1 parent 1a59b5e3e1
commit 0110de8104
28 files changed
+309 -577

No files matched your search

@@ -23,7 +23,7 @@ import android.location.LocationManager
import androidx.room.Room
import com.rtbishop.look4sat.data.*
import com.rtbishop.look4sat.domain.predict4kotlin.QthConverter
import com.rtbishop.look4sat.framework.DefaultLocationSource
import com.rtbishop.look4sat.framework.PreferencesProvider
import com.rtbishop.look4sat.framework.api.NetworkDataSource
import com.rtbishop.look4sat.framework.api.SatelliteService
import com.rtbishop.look4sat.framework.db.RoomConverters
@@ -52,20 +52,21 @@ object DataSourceModule {
@Provides
@Singleton
fun provideLocationSource(
fun providePreferenceSource(
qthConverter: QthConverter,
locationManager: LocationManager,
preferences: SharedPreferences
): LocationSource {
return DefaultLocationSource(locationManager, preferences)
): PreferenceSource {
return PreferencesProvider(qthConverter, locationManager, preferences)
}
@Provides
@Singleton
fun provideLocationRepo(
locationSource: LocationSource,
qthConverter: QthConverter
): LocationRepo {
return LocationRepo(locationSource, qthConverter)
fun providePassesRepo(
preferenceSource: PreferenceSource,
@DefaultDispatcher defaultDispatcher: CoroutineDispatcher
): PassesRepo {
return PassesRepo(preferenceSource, defaultDispatcher)
}
@Provides
@@ -39,18 +39,18 @@ object InteractorsModule {
}
@Provides
fun provideGetTransmittersForSatUseCase(satelliteRepo: SatelliteRepo): GetTransmittersForSat {
return GetTransmittersForSat(satelliteRepo)
fun provideGetSatTransmittersUseCase(satelliteRepo: SatelliteRepo): GetSatTransmitters {
return GetSatTransmitters(satelliteRepo)
}
@Provides
fun provideImportDataFromStreamUseCase(satelliteRepo: SatelliteRepo): ImportDataFromStream {
return ImportDataFromStream(satelliteRepo)
fun provideUpdateEntriesFromFileUseCase(satelliteRepo: SatelliteRepo): UpdateEntriesFromFile {
return UpdateEntriesFromFile(satelliteRepo)
}
@Provides
fun provideImportDataFromWebUseCase(satelliteRepo: SatelliteRepo): ImportDataFromWeb {
return ImportDataFromWeb(satelliteRepo)
fun provideUpdateEntriesFromWebUseCase(satelliteRepo: SatelliteRepo): UpdateEntriesFromWeb {
return UpdateEntriesFromWeb(satelliteRepo)
}
@Provides
@@ -1,62 +0,0 @@
package com.rtbishop.look4sat.framework
import android.content.SharedPreferences
import android.hardware.GeomagneticField
import android.location.LocationManager
import androidx.core.content.edit
import com.rtbishop.look4sat.data.LocationSource
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
import com.rtbishop.look4sat.utility.round
import javax.inject.Inject
class DefaultLocationSource @Inject constructor(
private val locationManager: LocationManager,
private val preferences: SharedPreferences
) : LocationSource {
companion object {
const val keyLatitude = "stationLat"
const val keyLongitude = "stationLon"
const val keyAltitude = "stationAlt"
const val keyPositionGPS = "setPositionGPS"
const val keyPositionQTH = "setPositionQTH"
}
override fun getLastKnownLocation(): StationPosition? {
return try {
val location = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER)
if (location == null) null
else {
val latitude = location.latitude.round(4)
val longitude = location.longitude.round(4)
val altitude = location.altitude.round(1)
return StationPosition(latitude, longitude, altitude)
}
} catch (exception: SecurityException) {
null
}
}
override fun getMagDeclination(position: StationPosition): Float {
val lat = position.latitude.toFloat()
val lon = position.longitude.toFloat()
val alt = position.altitude.toFloat()
return GeomagneticField(lat, lon, alt, System.currentTimeMillis()).declination
}
override fun loadStationPosition(): StationPosition {
val defaultSP = "0.0"
val latitude = preferences.getString(keyLatitude, null) ?: defaultSP
val longitude = preferences.getString(keyLongitude, null) ?: defaultSP
val altitude = preferences.getString(keyAltitude, null) ?: defaultSP
return StationPosition(latitude.toDouble(), longitude.toDouble(), altitude.toDouble())
}
override fun saveStationPosition(position: StationPosition) {
preferences.edit {
putString(keyLatitude, position.latitude.toString())
putString(keyLongitude, position.longitude.toString())
putString(keyAltitude, position.altitude.toString())
}
}
}
@@ -0,0 +1,155 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2021 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 3 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, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.framework
import android.content.SharedPreferences
import android.hardware.GeomagneticField
import android.location.LocationManager
import androidx.core.content.edit
import com.rtbishop.look4sat.data.PreferenceSource
import com.rtbishop.look4sat.domain.predict4kotlin.QthConverter
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
import com.rtbishop.look4sat.utility.round
import javax.inject.Inject
class PreferencesProvider @Inject constructor(
private val qthConverter: QthConverter,
private val locationManager: LocationManager,
private val preferences: SharedPreferences
) : PreferenceSource {
companion object {
const val keyModes = "satModes"
const val keyCompass = "compass"
const val keyTextLabels = "shouldUseTextLabels"
const val keyTimeUTC = "timeUTC"
const val keyHoursAhead = "hoursAhead"
const val keyMinElevation = "minElevation"
const val keyIsFirstLaunch = "shouldShowSplash"
const val keyRotator = "isRotatorEnabled"
const val keyRotatorAddress = "rotatorAddress"
const val keyRotatorPort = "rotatorPort"
const val keyLatitude = "stationLat"
const val keyLongitude = "stationLon"
const val keyAltitude = "stationAlt"
const val keyPositionGPS = "setPositionGPS"
const val keyPositionQTH = "setPositionQTH"
}
override fun positionToQTH(lat: Double, lon: Double): String? {
return qthConverter.positionToQTH(lat, lon)
}
override fun loadStationPosition(): StationPosition {
val defaultSP = "0.0"
val latitude = preferences.getString(keyLatitude, null) ?: defaultSP
val longitude = preferences.getString(keyLongitude, null) ?: defaultSP
val altitude = preferences.getString(keyAltitude, null) ?: defaultSP
return StationPosition(latitude.toDouble(), longitude.toDouble(), altitude.toDouble())
}
override fun saveStationPosition(position: StationPosition) {
preferences.edit {
putString(keyLatitude, position.latitude.toString())
putString(keyLongitude, position.longitude.toString())
putString(keyAltitude, position.altitude.toString())
}
}
override fun updatePositionFromGPS(): Boolean {
return try {
val location = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER)
if (location == null) false
else {
val latitude = location.latitude.round(4)
val longitude = location.longitude.round(4)
val altitude = location.altitude.round(1)
val stationPosition = StationPosition(latitude, longitude, altitude)
saveStationPosition(stationPosition)
return true
}
} catch (exception: SecurityException) {
false
}
}
override fun updatePositionFromQTH(qthString: String): Boolean {
val position = qthConverter.qthToPosition(qthString) ?: return false
val stationPosition = StationPosition(position.latitude, position.longitude, 0.0)
saveStationPosition(stationPosition)
return true
}
override fun getMagDeclination(): Float {
val stationPosition = loadStationPosition()
val lat = stationPosition.latitude.toFloat()
val lon = stationPosition.longitude.toFloat()
val alt = stationPosition.altitude.toFloat()
return GeomagneticField(lat, lon, alt, System.currentTimeMillis()).declination
}
override fun getHoursAhead(): Int {
return preferences.getInt(keyHoursAhead, 8)
}
override fun getMinElevation(): Double {
return preferences.getInt(keyMinElevation, 16).toDouble()
}
override fun shouldUseTextLabels(): Boolean {
return preferences.getBoolean(keyTextLabels, false)
}
override fun shouldUseUTC(): Boolean {
return preferences.getBoolean(keyTimeUTC, false)
}
override fun shouldUseCompass(): Boolean {
return preferences.getBoolean(keyCompass, true)
}
override fun isFirstLaunch(): Boolean {
return preferences.getBoolean(keyIsFirstLaunch, true)
}
override fun setFirstLaunchDone() {
preferences.edit { putBoolean(keyIsFirstLaunch, false) }
}
override fun saveModesSelection(modes: List<String>) {
val modesSet = modes.toSet()
preferences.edit {
putStringSet(keyModes, modesSet)
}
}
override fun loadModesSelection(): List<String> {
preferences.getStringSet(keyModes, setOf())?.let { modesSet ->
return modesSet.toList().sorted()
}
return emptyList()
}
override fun getRotatorServer(): Pair<String, Int>? {
return if (preferences.getBoolean(keyRotator, false)) {
val address = preferences.getString(keyRotatorAddress, null) ?: "127.0.0.1"
val port = preferences.getString(keyRotatorPort, null) ?: "4096"
Pair(address, port.toInt())
} else null
}
}
@@ -1,124 +0,0 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2021 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 3 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, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.framework
import android.content.SharedPreferences
import androidx.core.content.edit
import com.rtbishop.look4sat.framework.model.TleSource
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class PrefsManager @Inject constructor(private val preferences: SharedPreferences, moshi: Moshi) {
private val sourcesType = Types.newParameterizedType(List::class.java, TleSource::class.java)
private val sourcesAdapter = moshi.adapter<List<TleSource>>(sourcesType)
companion object {
const val keySources = "sourcesListJson"
const val keyModes = "satModes"
const val keyCompass = "compass"
const val keyTextLabels = "shouldUseTextLabels"
const val keyTimeUTC = "timeUTC"
const val keyHoursAhead = "hoursAhead"
const val keyMinElevation = "minElevation"
const val keyIsFirstLaunch = "shouldShowSplash"
const val keyRotator = "isRotatorEnabled"
const val keyRotatorAddress = "rotatorAddress"
const val keyRotatorPort = "rotatorPort"
}
fun getHoursAhead(): Int {
return preferences.getInt(keyHoursAhead, 8)
}
fun getMinElevation(): Double {
return preferences.getInt(keyMinElevation, 16).toDouble()
}
fun shouldUseTextLabels(): Boolean {
return preferences.getBoolean(keyTextLabels, false)
}
fun shouldUseUTC(): Boolean {
return preferences.getBoolean(keyTimeUTC, false)
}
fun shouldUseCompass(): Boolean {
return preferences.getBoolean(keyCompass, true)
}
fun isFirstLaunch(): Boolean {
return preferences.getBoolean(keyIsFirstLaunch, true)
}
fun setFirstLaunchDone() {
preferences.edit { putBoolean(keyIsFirstLaunch, false) }
}
fun loadTleSources(): List<TleSource> {
return try {
val sourcesString = preferences.getString(keySources, String())
if (sourcesString.isNullOrEmpty()) {
loadDefaultSources()
} else {
sourcesAdapter.fromJson(sourcesString) ?: loadDefaultSources()
}
} catch (exception: ClassCastException) {
loadDefaultSources()
}
}
fun saveTleSources(sources: List<TleSource>) {
val sourcesJson = sourcesAdapter.toJson(sources)
preferences.edit { putString(keySources, sourcesJson) }
}
fun loadDefaultSources(): List<TleSource> {
return listOf(
TleSource("https://celestrak.com/NORAD/elements/active.txt"),
TleSource("https://amsat.org/tle/current/nasabare.txt"),
TleSource("https://www.prismnet.com/~mmccants/tles/classfd.zip"),
TleSource("https://www.prismnet.com/~mmccants/tles/inttles.zip")
)
}
fun saveModesSelection(modes: List<String>) {
val modesSet = modes.toSet()
preferences.edit {
putStringSet(keyModes, modesSet)
}
}
fun loadModesSelection(): List<String> {
preferences.getStringSet(keyModes, setOf())?.let { modesSet ->
return modesSet.toList().sorted()
}
return emptyList()
}
fun getRotatorServer(): Pair<String, Int>? {
return if (preferences.getBoolean(keyRotator, false)) {
val address = preferences.getString(keyRotatorAddress, null) ?: "127.0.0.1"
val port = preferences.getString(keyRotatorPort, null) ?: "4096"
Pair(address, port.toInt())
} else null
}
}
@@ -29,7 +29,7 @@ class RoomDataSource(private val satelliteDao: SatelliteDao) : LocalDataSource {
satelliteDao.updateEntriesSelection(catNums, isSelected)
}
override fun getTransmittersForSat(catNum: Int): Flow<List<SatTrans>> {
override fun getSatTransmitters(catNum: Int): Flow<List<SatTrans>> {
return satelliteDao.getSatTransmitters(catNum)
.map { satTransList -> DataMapper.satTransListToDomainTransList(satTransList) }
}
@@ -1,20 +0,0 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2021 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 3 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, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.framework.model
class TleSource(var url: String = String())
@@ -25,7 +25,7 @@ import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.databinding.ActivityMainBinding
import com.rtbishop.look4sat.framework.PrefsManager
import com.rtbishop.look4sat.framework.PreferencesProvider
import com.rtbishop.look4sat.utility.navigateSafe
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@@ -34,7 +34,7 @@ import javax.inject.Inject
class Look4SatActivity : AppCompatActivity() {
@Inject
lateinit var prefsManager: PrefsManager
lateinit var preferenceSource: PreferencesProvider
@SuppressLint("SourceLockedOrientationActivity")
override fun onCreate(savedInstanceState: Bundle?) {
@@ -45,8 +45,8 @@ class Look4SatActivity : AppCompatActivity() {
setContentView(binding.root)
val navHost = supportFragmentManager.findFragmentById(R.id.nav_host) as NavHostFragment
binding.navBottom.setupWithNavController(navHost.navController)
if (prefsManager.isFirstLaunch()) {
prefsManager.setFirstLaunchDone()
if (preferenceSource.isFirstLaunch()) {
preferenceSource.setFirstLaunchDone()
navHost.navController.navigateSafe(R.id.nav_dialog_splash)
}
}
@@ -22,18 +22,14 @@ import android.view.View
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.SimpleItemAnimator
import com.google.android.material.snackbar.Snackbar
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.framework.model.Result
import com.rtbishop.look4sat.databinding.FragmentEntriesBinding
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.framework.model.TleSource
import com.rtbishop.look4sat.framework.model.Result
import com.rtbishop.look4sat.utility.RecyclerDivider
import com.rtbishop.look4sat.utility.getNavResult
import com.rtbishop.look4sat.utility.navigateSafe
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -42,7 +38,7 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) {
private val viewModel: EntriesViewModel by viewModels()
private val contentContract = ActivityResultContracts.GetContent()
private val filePicker = registerForActivityResult(contentContract) { uri ->
uri?.let { viewModel.importSatDataFromFile(uri) }
uri?.let { viewModel.updateEntriesFromFile(uri) }
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -62,9 +58,7 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) {
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
addItemDecoration(RecyclerDivider(R.drawable.rec_divider_light))
}
importWeb.setOnClickListener {
findNavController().navigateSafe(R.id.action_entries_to_sources)
}
importWeb.setOnClickListener { viewModel.updateEntriesFromWeb(null) }
importFile.setOnClickListener { filePicker.launch("*/*") }
selectMode.setOnClickListener { viewModel.createModesDialog(requireContext()).show() }
selectAll.setOnClickListener { viewModel.selectCurrentItems() }
@@ -73,9 +67,6 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) {
viewModel.satData.observe(viewLifecycleOwner, { satData ->
handleSatData(satData, binding, entriesAdapter)
})
getNavResult<List<String>>(R.id.nav_entries, "sources") { navResult ->
handleNavResult(navResult)
}
}
private fun handleSatData(
@@ -97,15 +88,11 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) {
is Result.Error -> {
binding.entriesProgress.visibility = View.INVISIBLE
binding.entriesRecycler.visibility = View.VISIBLE
Snackbar.make(requireView(), R.string.entries_update_error, Snackbar.LENGTH_SHORT)
.setAnchorView(R.id.nav_bottom).show()
val errorMsg = getString(R.string.entries_update_error)
Snackbar.make(requireView(), errorMsg, Snackbar.LENGTH_SHORT).apply {
setAnchorView(R.id.nav_bottom)
}.show()
}
}
}
private fun handleNavResult(result: List<String>) {
result.map { sourceUrl -> TleSource(sourceUrl) }.let { sources ->
viewModel.importSatDataFromSources(sources)
}
}
}
@@ -26,32 +26,29 @@ import androidx.lifecycle.*
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.framework.PreferencesProvider
import com.rtbishop.look4sat.framework.model.Result
import com.rtbishop.look4sat.framework.model.TleSource
import com.rtbishop.look4sat.interactors.GetSatItems
import com.rtbishop.look4sat.interactors.ImportDataFromStream
import com.rtbishop.look4sat.interactors.ImportDataFromWeb
import com.rtbishop.look4sat.interactors.UpdateEntriesFromFile
import com.rtbishop.look4sat.interactors.UpdateEntriesFromWeb
import com.rtbishop.look4sat.interactors.UpdateEntriesSelection
import com.rtbishop.look4sat.framework.PrefsManager
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.*
import javax.inject.Inject
import kotlin.system.measureTimeMillis
@HiltViewModel
class EntriesViewModel @Inject constructor(
private val prefsManager: PrefsManager,
private val preferenceSource: PreferencesProvider,
private val resolver: ContentResolver,
private val getSatItems: GetSatItems,
private val importDataFromStream: ImportDataFromStream,
private val importDataFromWeb: ImportDataFromWeb,
private val updateEntriesFromFile: UpdateEntriesFromFile,
private val updateEntriesFromWeb: UpdateEntriesFromWeb,
private val updateEntriesSelection: UpdateEntriesSelection,
) : ViewModel(), EntriesAdapter.EntriesClickListener, SearchView.OnQueryTextListener {
private val transModes = MutableLiveData(prefsManager.loadModesSelection())
private val transModes = MutableLiveData(preferenceSource.loadModesSelection())
private val currentQuery = MutableLiveData(String())
private val itemsWithModes = transModes.switchMap { modes ->
liveData { getSatItems().collect { emit(filterByModes(it, modes)) } }
@@ -65,32 +62,22 @@ class EntriesViewModel @Inject constructor(
private var shouldSelectAll = true
val satData: LiveData<Result<List<SatItem>>> = _satData
fun importSatDataFromFile(uri: Uri) {
fun updateEntriesFromFile(uri: Uri) {
viewModelScope.launch {
_satData.value = Result.InProgress
runCatching {
resolver.openInputStream(uri)?.use { stream ->
importDataFromStream(stream)
}
resolver.openInputStream(uri)?.use { stream -> updateEntriesFromFile(stream) }
}.onFailure { _satData.value = Result.Error(it) }
}
}
fun importSatDataFromSources(sources: List<TleSource>) {
fun updateEntriesFromWeb(sources: List<String>?) {
viewModelScope.launch {
_satData.value = Result.InProgress
val satSources = if (sources.isNotEmpty()) sources
else prefsManager.loadDefaultSources()
val updateMillis = measureTimeMillis {
try {
prefsManager.saveTleSources(satSources)
importDataFromWeb(satSources.map { it.url })
} catch (exception: Exception) {
_satData.value = Result.Error(exception)
Timber.d(exception)
}
}
Timber.d("Update from WEB took $updateMillis ms")
runCatching {
if (sources == null) updateEntriesFromWeb()
else updateEntriesFromWeb(sources)
}.onFailure { _satData.value = Result.Error(it) }
}
}
@@ -111,7 +98,7 @@ class EntriesViewModel @Inject constructor(
"PSK", "PSK31", "PSK63", "QPSK", "QPSK31", "QPSK63", "SSTV", "USB", "WSJT"
)
val savedModes = BooleanArray(modes.size)
val selectedModes = prefsManager.loadModesSelection().toMutableList()
val selectedModes = preferenceSource.loadModesSelection().toMutableList()
selectedModes.forEach { savedModes[modes.indexOf(it)] = true }
val dialogBuilder = MaterialAlertDialogBuilder(context).apply {
setTitle(context.getString(R.string.modes_title))
@@ -123,7 +110,7 @@ class EntriesViewModel @Inject constructor(
}
setPositiveButton(context.getString(android.R.string.ok)) { _, _ ->
transModes.value = selectedModes
prefsManager.saveModesSelection(selectedModes)
preferenceSource.saveModesSelection(selectedModes)
}
setNeutralButton(context.getString(android.R.string.cancel)) { dialog, _ ->
dialog.dismiss()
@@ -18,14 +18,13 @@
package com.rtbishop.look4sat.presentation.mapScreen
import androidx.lifecycle.*
import com.rtbishop.look4sat.data.LocationRepo
import com.rtbishop.look4sat.data.PreferenceSource
import com.rtbishop.look4sat.di.DefaultDispatcher
import com.rtbishop.look4sat.domain.predict4kotlin.Position
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
import com.rtbishop.look4sat.framework.model.SatData
import com.rtbishop.look4sat.interactors.GetSelectedSatellites
import com.rtbishop.look4sat.framework.PrefsManager
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
import java.util.*
@@ -38,12 +37,11 @@ import kotlin.math.sqrt
@HiltViewModel
class MapViewModel @Inject constructor(
private val getSelectedSatellites: GetSelectedSatellites,
private val prefsManager: PrefsManager,
private val locationRepo: LocationRepo,
private val preferenceSource: PreferenceSource,
@DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher
) : ViewModel() {
private val gsp = locationRepo.getStationPosition()
private val gsp = preferenceSource.loadStationPosition()
private var dataUpdateJob: Job? = null
private var allSatList = listOf<Satellite>()
private lateinit var selectedSat: Satellite
@@ -78,7 +76,7 @@ class MapViewModel @Inject constructor(
}
fun shouldUseTextLabels(): Boolean {
return prefsManager.shouldUseTextLabels()
return preferenceSource.shouldUseTextLabels()
}
fun scrollSelection(decrement: Boolean) {
@@ -172,7 +170,8 @@ class MapViewModel @Inject constructor(
val osmLat = getOsmLat(Math.toDegrees(satPos.latitude))
val osmLon = getOsmLon(Math.toDegrees(satPos.longitude))
val osmPos = Position(osmLat, osmLon)
val qthLoc = locationRepo.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --"
val qthLoc =
preferenceSource.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --"
val velocity = getOrbitalVelocity(satPos.altitude)
val satData = SatData(
sat, sat.tle.catnum, sat.tle.name, satPos.range,
@@ -22,10 +22,10 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.rtbishop.look4sat.framework.model.Result
import com.rtbishop.look4sat.utility.PassesRepo
import com.rtbishop.look4sat.data.PassesRepo
import com.rtbishop.look4sat.interactors.GetSelectedSatellites
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
import com.rtbishop.look4sat.framework.PrefsManager
import com.rtbishop.look4sat.framework.PreferencesProvider
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.collect
@@ -35,7 +35,7 @@ import javax.inject.Inject
class PassesViewModel @Inject constructor(
private val getSelectedSatellites: GetSelectedSatellites,
private val passesRepo: PassesRepo,
private val prefsManager: PrefsManager
private val preferenceSource: PreferencesProvider
) : ViewModel() {
private val _passes = MutableLiveData<Result<List<SatPass>>>(Result.InProgress)
@@ -64,7 +64,7 @@ class PassesViewModel @Inject constructor(
}
fun shouldUseUTC(): Boolean {
return prefsManager.shouldUseUTC()
return preferenceSource.shouldUseUTC()
}
private suspend fun tickPasses(passes: List<SatPass>) = withContext(Dispatchers.Default) {
@@ -18,14 +18,13 @@
package com.rtbishop.look4sat.presentation.polarScreen
import androidx.lifecycle.*
import com.rtbishop.look4sat.data.LocationRepo
import com.rtbishop.look4sat.data.PreferenceSource
import com.rtbishop.look4sat.di.IoDispatcher
import com.rtbishop.look4sat.domain.model.SatTrans
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
import com.rtbishop.look4sat.interactors.GetTransmittersForSat
import com.rtbishop.look4sat.interactors.GetSatTransmitters
import com.rtbishop.look4sat.framework.OrientationProvider
import com.rtbishop.look4sat.utility.PassesRepo
import com.rtbishop.look4sat.framework.PrefsManager
import com.rtbishop.look4sat.data.PassesRepo
import com.rtbishop.look4sat.utility.round
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
@@ -37,11 +36,10 @@ import javax.inject.Inject
@HiltViewModel
class PolarViewModel @Inject constructor(
private val locationRepo: LocationRepo,
private val orientationProvider: OrientationProvider,
private val prefsManager: PrefsManager,
private val preferenceSource: PreferenceSource,
private val passesRepo: PassesRepo,
private val getTransmittersForSat: GetTransmittersForSat,
private val getSatTransmitters: GetSatTransmitters,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
) : ViewModel(), OrientationProvider.OrientationListener {
@@ -62,20 +60,20 @@ class PolarViewModel @Inject constructor(
}
fun enableSensor() {
if (prefsManager.shouldUseCompass()) orientationProvider.startListening(this)
if (preferenceSource.shouldUseCompass()) orientationProvider.startListening(this)
}
fun disableSensor() {
if (prefsManager.shouldUseCompass()) orientationProvider.stopListening()
if (preferenceSource.shouldUseCompass()) orientationProvider.stopListening()
}
override fun onOrientationChanged(azimuth: Float, pitch: Float, roll: Float) {
_orientation.value = Triple(azimuth + locationRepo.getMagDeclination(), pitch, roll)
_orientation.value = Triple(azimuth + preferenceSource.getMagDeclination(), pitch, roll)
}
private fun initRotatorControl(satPass: SatPass) {
viewModelScope.launch {
val rotatorPrefs = prefsManager.getRotatorServer()
val rotatorPrefs = preferenceSource.getRotatorServer()
if (rotatorPrefs != null) {
runCatching {
withContext(ioDispatcher) {
@@ -99,7 +97,7 @@ class PolarViewModel @Inject constructor(
private fun processTransmitters(satPass: SatPass) {
viewModelScope.launch {
getTransmittersForSat(satPass.catNum).collect { transList ->
getSatTransmitters(satPass.catNum).collect { transList ->
while (isActive) {
val timeNow = Date()
val copiedList = transList.map { it.copy() }
@@ -30,9 +30,8 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.snackbar.Snackbar
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.data.LocationRepo
import com.rtbishop.look4sat.framework.DefaultLocationSource
import com.rtbishop.look4sat.framework.PrefsManager
import com.rtbishop.look4sat.data.PreferenceSource
import com.rtbishop.look4sat.framework.PreferencesProvider
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@@ -40,10 +39,7 @@ import javax.inject.Inject
class PrefsFragment : PreferenceFragmentCompat() {
@Inject
lateinit var locationRepo: LocationRepo
@Inject
lateinit var prefsManager: PrefsManager
lateinit var preferenceSource: PreferenceSource
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
@@ -61,20 +57,20 @@ class PrefsFragment : PreferenceFragmentCompat() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
findPreference<Preference>(DefaultLocationSource.keyPositionGPS)?.apply {
findPreference<Preference>(PreferencesProvider.keyPositionGPS)?.apply {
setOnPreferenceClickListener {
updatePositionFromGPS()
return@setOnPreferenceClickListener true
}
}
findPreference<Preference>(DefaultLocationSource.keyPositionQTH)?.apply {
findPreference<Preference>(PreferencesProvider.keyPositionQTH)?.apply {
setOnPreferenceChangeListener { _, newValue ->
updatePositionFromQth(newValue.toString())
}
}
findPreference<EditTextPreference>(PrefsManager.keyRotatorAddress)?.apply {
findPreference<EditTextPreference>(PreferencesProvider.keyRotatorAddress)?.apply {
setOnPreferenceChangeListener { _, newValue ->
if (Patterns.IP_ADDRESS.matcher(newValue.toString()).matches()) {
return@setOnPreferenceChangeListener true
@@ -85,7 +81,7 @@ class PrefsFragment : PreferenceFragmentCompat() {
}
}
findPreference<EditTextPreference>(PrefsManager.keyRotatorPort)?.apply {
findPreference<EditTextPreference>(PreferencesProvider.keyRotatorPort)?.apply {
setOnBindEditTextListener { it.inputType = InputType.TYPE_CLASS_NUMBER }
setOnPreferenceChangeListener { _, newValue ->
val portValue = newValue.toString()
@@ -100,7 +96,7 @@ class PrefsFragment : PreferenceFragmentCompat() {
}
private fun updatePositionFromQth(qthString: String): Boolean {
return if (locationRepo.updatePositionFromQTH(qthString)) {
return if (preferenceSource.updatePositionFromQTH(qthString)) {
showSnack(getString(R.string.pref_pos_success))
true
} else {
@@ -113,7 +109,7 @@ class PrefsFragment : PreferenceFragmentCompat() {
val locPermString = Manifest.permission.ACCESS_FINE_LOCATION
val locPermResult = ContextCompat.checkSelfPermission(requireContext(), locPermString)
if (locPermResult == PackageManager.PERMISSION_GRANTED) {
if (locationRepo.updatePositionFromGPS()) {
if (preferenceSource.updatePositionFromGPS()) {
showSnack(getString(R.string.pref_pos_success))
} else showSnack(getString(R.string.pref_pos_gps_null))
} else requestPermissionLauncher.launch(locPermString)
@@ -1,70 +0,0 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2021 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 3 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, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.presentation.sourcesDialog
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.widget.doOnTextChanged
import androidx.recyclerview.widget.RecyclerView
import com.rtbishop.look4sat.databinding.ItemTleSourceBinding
import com.rtbishop.look4sat.framework.model.TleSource
class SourcesAdapter(private val sources: MutableList<TleSource> = mutableListOf()) :
RecyclerView.Adapter<SourcesAdapter.TleSourceHolder>() {
fun getSources(): List<TleSource> {
return sources.filter { it.url.contains("https://") }
}
fun setSources(list: List<TleSource>) {
sources.clear()
sources.addAll(list)
}
fun addSource() {
sources.add(TleSource())
notifyItemInserted(itemCount - 1)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TleSourceHolder {
val binding = ItemTleSourceBinding
.inflate(LayoutInflater.from(parent.context), parent, false)
return TleSourceHolder(binding)
}
override fun onBindViewHolder(holder: TleSourceHolder, position: Int) {
holder.bind(sources[position])
}
override fun getItemCount(): Int {
return sources.size
}
inner class TleSourceHolder(private val binding: ItemTleSourceBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(source: TleSource) {
binding.tleSourceUrl.setText(source.url)
binding.tleSourceUrl.doOnTextChanged { text, _, _, _ -> source.url = text.toString() }
binding.tleSourceInputLayout.setEndIconOnClickListener {
sources.remove(source)
notifyItemRemoved(adapterPosition)
}
}
}
}
@@ -1,66 +0,0 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2021 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 3 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, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.presentation.sourcesDialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.appcompat.app.AppCompatDialogFragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.framework.PrefsManager
import com.rtbishop.look4sat.databinding.DialogSourcesBinding
import com.rtbishop.look4sat.utility.setNavResult
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class SourcesDialog : AppCompatDialogFragment() {
@Inject
lateinit var prefsManager: PrefsManager
override fun onCreateView(inflater: LayoutInflater, group: ViewGroup?, state: Bundle?): View? {
return inflater.inflate(R.layout.dialog_sources, group, false)
}
override fun onViewCreated(view: View, state: Bundle?) {
super.onViewCreated(view, state)
val sourcesAdapter = SourcesAdapter().apply { setSources(prefsManager.loadTleSources()) }
DialogSourcesBinding.bind(view).apply {
dialog?.window?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT
)
sourcesRecycler.apply {
adapter = sourcesAdapter
layoutManager = LinearLayoutManager(requireContext())
}
sourceBtnAdd.setOnClickListener {
sourcesAdapter.addSource()
}
sourcesBtnPos.setOnClickListener {
setNavResult("sources", sourcesAdapter.getSources().map { it.url })
dismiss()
}
sourcesBtnNeg.setOnClickListener { dismiss() }
}
}
}
@@ -19,13 +19,9 @@ package com.rtbishop.look4sat.utility
import android.os.Bundle
import androidx.annotation.IdRes
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.navigation.NavController
import androidx.navigation.NavOptions
import androidx.navigation.Navigator
import androidx.navigation.fragment.findNavController
import java.util.concurrent.TimeUnit
fun Long.toTimerString(): String {
@@ -53,26 +49,3 @@ fun NavController.navigateSafe(
navigate(resId, args, navOptions, navExtras)
}
}
fun <T> Fragment.setNavResult(key: String, value: T) {
findNavController().previousBackStackEntry?.savedStateHandle?.set(key, value)
}
fun <T> Fragment.getNavResult(@IdRes id: Int, key: String, onResult: (result: T) -> Unit) {
val navBackStackEntry = findNavController().getBackStackEntry(id)
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME
&& navBackStackEntry.savedStateHandle.contains(key)
) {
val result = navBackStackEntry.savedStateHandle.get<T>(key)
result?.let(onResult)
navBackStackEntry.savedStateHandle.remove<T>(key)
}
}
navBackStackEntry.lifecycle.addObserver(observer)
viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_DESTROY) {
navBackStackEntry.lifecycle.removeObserver(observer)
}
})
}
-11
View File
@@ -16,13 +16,6 @@
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
<action
android:id="@+id/action_entries_to_sources"
app:destination="@id/nav_dialog_sources"
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
@@ -66,10 +59,6 @@
android:id="@+id/nav_info"
android:name="com.rtbishop.look4sat.presentation.infoScreen.InfoFragment"
tools:layout="@layout/fragment_info" />
<dialog
android:id="@+id/nav_dialog_sources"
android:name="com.rtbishop.look4sat.presentation.sourcesDialog.SourcesDialog"
tools:layout="@layout/dialog_sources" />
<dialog
android:id="@+id/nav_dialog_splash"
android:name="com.rtbishop.look4sat.presentation.splashDialog.SplashDialog"
@@ -10,13 +10,13 @@ interface LocalDataSource {
fun getSatItems(): Flow<List<SatItem>>
fun getSatTransmitters(catNum: Int): Flow<List<SatTrans>>
suspend fun getSelectedSatellites(): List<Satellite>
suspend fun updateEntries(entries: List<SatEntry>)
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean)
fun getTransmittersForSat(catNum: Int): Flow<List<SatTrans>>
suspend fun updateTransmitters(satelliteTrans: List<SatTrans>)
}
@@ -1,35 +0,0 @@
package com.rtbishop.look4sat.data
import com.rtbishop.look4sat.domain.predict4kotlin.QthConverter
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
class LocationRepo(
private val locationSource: LocationSource,
private val qthConverter: QthConverter
) {
fun getStationPosition(): StationPosition {
return locationSource.loadStationPosition()
}
fun getMagDeclination(): Float {
return locationSource.getMagDeclination(getStationPosition())
}
fun positionToQTH(lat: Double, lon: Double): String? {
return qthConverter.positionToQTH(lat, lon)
}
fun updatePositionFromGPS(): Boolean {
val stationPosition = locationSource.getLastKnownLocation() ?: return false
locationSource.saveStationPosition(stationPosition)
return true
}
fun updatePositionFromQTH(qthString: String): Boolean {
val position = qthConverter.qthToPosition(qthString) ?: return false
val stationPosition = StationPosition(position.latitude, position.longitude, 0.0)
locationSource.saveStationPosition(stationPosition)
return true
}
}
@@ -1,14 +0,0 @@
package com.rtbishop.look4sat.data
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
interface LocationSource {
fun getLastKnownLocation(): StationPosition?
fun getMagDeclination(position: StationPosition): Float
fun loadStationPosition(): StationPosition
fun saveStationPosition(position: StationPosition)
}
@@ -15,26 +15,19 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.utility
package com.rtbishop.look4sat.data
import com.rtbishop.look4sat.data.LocationRepo
import com.rtbishop.look4sat.di.DefaultDispatcher
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
import com.rtbishop.look4sat.framework.PrefsManager
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.withContext
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class PassesRepo @Inject constructor(
private val locationRepo: LocationRepo,
private val prefsManager: PrefsManager,
@DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher
class PassesRepo(
private val preferenceSource: PreferenceSource,
private val defaultDispatcher: CoroutineDispatcher
) {
private val _passes = MutableSharedFlow<List<SatPass>>(replay = 1)
private var selectedSatellites = emptyList<Satellite>()
@@ -64,15 +57,15 @@ class PassesRepo @Inject constructor(
}
private fun getPasses(satellite: Satellite, refDate: Date): List<SatPass> {
val predictor = satellite.getPredictor(locationRepo.getStationPosition())
return predictor.getPasses(refDate, prefsManager.getHoursAhead(), true)
val predictor = satellite.getPredictor(preferenceSource.loadStationPosition())
return predictor.getPasses(refDate, preferenceSource.getHoursAhead(), true)
}
private fun filterPasses(passes: List<SatPass>, refDate: Date): List<SatPass> {
val timeFuture = Date(refDate.time + (prefsManager.getHoursAhead() * 3600 * 1000))
val timeFuture = Date(refDate.time + (preferenceSource.getHoursAhead() * 3600 * 1000))
return passes.filter { it.losDate.after(refDate) }
.filter { it.aosDate.before(timeFuture) }
.filter { it.maxElevation > prefsManager.getMinElevation() }
.filter { it.maxElevation > preferenceSource.getMinElevation() }
.sortedBy { it.aosDate }
}
}
@@ -0,0 +1,38 @@
package com.rtbishop.look4sat.data
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
interface PreferenceSource {
fun positionToQTH(lat: Double, lon: Double): String?
fun loadStationPosition(): StationPosition
fun saveStationPosition(position: StationPosition)
fun updatePositionFromGPS(): Boolean
fun updatePositionFromQTH(qthString: String): Boolean
fun getMagDeclination(): Float
fun getHoursAhead(): Int
fun getMinElevation(): Double
fun shouldUseTextLabels(): Boolean
fun shouldUseUTC(): Boolean
fun shouldUseCompass(): Boolean
fun isFirstLaunch(): Boolean
fun setFirstLaunchDone()
fun saveModesSelection(modes: List<String>)
fun loadModesSelection(): List<String>
fun getRotatorServer(): Pair<String, Int>?
}
@@ -22,24 +22,23 @@ class SatelliteRepo(
return localSource.getSatItems()
}
fun getTransmittersForSat(catNum: Int): Flow<List<SatTrans>> {
return localSource.getTransmittersForSat(catNum)
fun getSatTransmitters(catNum: Int): Flow<List<SatTrans>> {
return localSource.getSatTransmitters(catNum)
}
suspend fun getSelectedSatellites(): List<Satellite> {
return localSource.getSelectedSatellites()
}
suspend fun importDataFromStream(stream: InputStream) = withContext(ioDispatcher) {
val importedEntries = Satellite.importElements(stream).map { tle -> SatEntry(tle) }
localSource.updateEntries(importedEntries)
suspend fun updateEntriesFromFile(stream: InputStream) = withContext(ioDispatcher) {
localSource.updateEntries(importSatEntries(stream))
}
suspend fun importDataFromWeb(sources: List<String>) {
suspend fun updateEntriesFromWeb(sources: List<String>) {
coroutineScope {
launch(ioDispatcher) {
val importedEntries = mutableListOf<SatEntry>()
val streams = mutableListOf<InputStream>()
val entries = mutableListOf<SatEntry>()
sources.forEach { source ->
remoteSource.fetchDataStream(source)?.let { stream ->
if (source.contains(".zip", true)) {
@@ -50,11 +49,8 @@ class SatelliteRepo(
}
}
}
streams.forEach { stream ->
val entries = Satellite.importElements(stream).map { tle -> SatEntry(tle) }
importedEntries.addAll(entries)
}
localSource.updateEntries(importedEntries)
streams.forEach { stream -> entries.addAll(importSatEntries(stream)) }
localSource.updateEntries(entries)
}
launch(ioDispatcher) {
val transmitters = remoteSource.fetchTransmitters().filter { it.isAlive }
@@ -66,4 +62,8 @@ class SatelliteRepo(
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
localSource.updateEntriesSelection(catNums, isSelected)
}
private fun importSatEntries(stream: InputStream): List<SatEntry> {
return Satellite.importElements(stream).map { tle -> SatEntry(tle) }
}
}
@@ -4,9 +4,9 @@ import com.rtbishop.look4sat.data.SatelliteRepo
import com.rtbishop.look4sat.domain.model.SatTrans
import kotlinx.coroutines.flow.Flow
class GetTransmittersForSat(private val satelliteRepo: SatelliteRepo) {
class GetSatTransmitters(private val satelliteRepo: SatelliteRepo) {
operator fun invoke(catNum: Int): Flow<List<SatTrans>> {
return satelliteRepo.getTransmittersForSat(catNum)
return satelliteRepo.getSatTransmitters(catNum)
}
}
@@ -1,10 +0,0 @@
package com.rtbishop.look4sat.interactors
import com.rtbishop.look4sat.data.SatelliteRepo
class ImportDataFromWeb(private val satelliteRepo: SatelliteRepo) {
suspend operator fun invoke(sources: List<String>) {
satelliteRepo.importDataFromWeb(sources)
}
}
@@ -3,9 +3,9 @@ package com.rtbishop.look4sat.interactors
import com.rtbishop.look4sat.data.SatelliteRepo
import java.io.InputStream
class ImportDataFromStream(private val satelliteRepo: SatelliteRepo) {
class UpdateEntriesFromFile(private val satelliteRepo: SatelliteRepo) {
suspend operator fun invoke(stream: InputStream) {
satelliteRepo.importDataFromStream(stream)
satelliteRepo.updateEntriesFromFile(stream)
}
}
@@ -0,0 +1,17 @@
package com.rtbishop.look4sat.interactors
import com.rtbishop.look4sat.data.SatelliteRepo
class UpdateEntriesFromWeb(private val satelliteRepo: SatelliteRepo) {
private val defaultSources = listOf(
"https://celestrak.com/NORAD/elements/active.txt",
"https://amsat.org/tle/current/nasabare.txt",
"https://www.prismnet.com/~mmccants/tles/classfd.zip",
"https://www.prismnet.com/~mmccants/tles/inttles.zip"
)
suspend operator fun invoke(sources: List<String> = defaultSources) {
satelliteRepo.updateEntriesFromWeb(sources)
}
}