Further code refactoring and cleanup

pull/87/head
Arty Bishop 2021-10-17 20:44:09 +01:00
rodzic 253321f3c2
commit bf72cd2061
20 zmienionych plików z 185 dodań i 224 usunięć

Wyświetl plik

@ -17,70 +17,39 @@
*/
package com.rtbishop.look4sat.framework
import com.rtbishop.look4sat.framework.model.SatEntry
import com.rtbishop.look4sat.framework.model.SatItem
import com.rtbishop.look4sat.framework.model.Transmitter
import com.rtbishop.look4sat.domain.model.SatEntry as DomainEntry
import com.rtbishop.look4sat.domain.model.SatItem as DomainItem
import com.rtbishop.look4sat.domain.model.Transmitter as DomainTrans
import com.rtbishop.look4sat.domain.model.Transmitter as DomainTransmitter
import com.rtbishop.look4sat.framework.model.SatEntry as FrameworkEntry
import com.rtbishop.look4sat.framework.model.SatItem as FrameworkItem
import com.rtbishop.look4sat.framework.model.Transmitter as FrameworkTransmitter
object DataMapper {
fun DomainEntry.toFramework() = FrameworkEntry(this.tle, this.isSelected)
// Presentation to Domain
fun DomainItem.toFramework() = FrameworkItem(this.catnum, this.name, this.isSelected, this.modes)
fun satEntryToDomainEntry(entry: SatEntry): DomainEntry {
return DomainEntry(entry.tle, entry.isSelected)
}
fun DomainTransmitter.toFramework() = FrameworkTransmitter(
this.uuid, this.info, this.isAlive, this.downlink,
this.uplink, this.mode, this.isInverted, this.catnum
)
fun satEntriesToDomainEntries(entries: List<SatEntry>): List<DomainEntry> {
return entries.map { entry -> satEntryToDomainEntry(entry) }
}
fun FrameworkEntry.toDomain() = DomainEntry(this.tle, this.isSelected)
fun satItemToDomainItem(item: SatItem): DomainItem {
return DomainItem(item.catnum, item.name, item.isSelected, item.modes)
}
fun FrameworkItem.toDomain() = DomainItem(this.catnum, this.name, this.isSelected, this.modes)
fun satItemsToDomainItems(items: List<SatItem>): List<DomainItem> {
return items.map { item -> satItemToDomainItem(item) }
}
fun FrameworkTransmitter.toDomain() = DomainTransmitter(
this.uuid, this.info, this.isAlive, this.downlink,
this.uplink, this.mode, this.isInverted, this.catnum
)
fun satTransToDomainTrans(transmitter: Transmitter): DomainTrans {
return DomainTrans(
transmitter.uuid, transmitter.info, transmitter.isAlive, transmitter.downlink,
transmitter.uplink, transmitter.mode, transmitter.isInverted, transmitter.catnum
)
}
fun List<DomainEntry>.toFrameworkEntries() = this.map { it.toFramework() }
fun satTransListToDomainTransList(transmitters: List<Transmitter>): List<DomainTrans> {
return transmitters.map { transmitter -> satTransToDomainTrans(transmitter) }
}
fun List<DomainItem>.toFrameworkItems() = this.map { it.toFramework() }
// Domain to Presentation
fun List<DomainTransmitter>.toFramework() = this.map { it.toFramework() }
fun domainEntryToSatEntry(entry: DomainEntry): SatEntry {
return SatEntry(entry.tle, entry.isSelected)
}
fun List<FrameworkEntry>.toDomainEntries() = this.map { it.toDomain() }
fun domainEntriesToSatEntries(entries: List<DomainEntry>): List<SatEntry> {
return entries.map { entry -> domainEntryToSatEntry(entry) }
}
fun List<FrameworkItem>.toDomainItems() = this.map { it.toDomain() }
fun domainItemToSatItem(item: DomainItem): SatItem {
return SatItem(item.catnum, item.name, item.isSelected, item.modes)
}
fun domainItemsToSatItems(items: List<DomainItem>): List<SatItem> {
return items.map { item -> domainItemToSatItem(item) }
}
fun domainTransToSatTrans(transmitter: DomainTrans): Transmitter {
return Transmitter(
transmitter.uuid, transmitter.info, transmitter.isAlive, transmitter.downlink,
transmitter.uplink, transmitter.mode, transmitter.isInverted, transmitter.catnum
)
}
fun domainTransListToSatTransList(transmitters: List<DomainTrans>): List<Transmitter> {
return transmitters.map { transmitter -> domainTransToSatTrans(transmitter) }
}
}
fun List<FrameworkTransmitter>.toDomain() = this.map { it.toDomain() }

Wyświetl plik

@ -27,38 +27,38 @@ interface EntriesDao {
@Transaction
@Query("SELECT catnum, name, isSelected FROM entries ORDER BY name ASC")
fun getSatItems(): Flow<List<SatItem>>
fun getSatelliteItems(): Flow<List<SatItem>>
@Query("SELECT * FROM entries WHERE isSelected = 1")
suspend fun getSelectedSatellites(): List<SatEntry>
@Transaction
suspend fun updateEntries(entries: List<SatEntry>) {
val entriesSelection = getEntriesSelection()
val savedSelection = getSelection()
insertEntries(entries)
restoreEntriesSelection(entriesSelection, true)
restoreSelection(savedSelection, true)
}
@Query("SELECT catnum FROM entries WHERE isSelected = 1")
suspend fun getEntriesSelection(): List<Int>
suspend fun getSelection(): List<Int>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertEntries(entries: List<SatEntry>)
@Transaction
suspend fun updateEntriesSelection(catnums: List<Int>, isSelected: Boolean) {
catnums.forEach { catnum -> updateEntrySelection(catnum, isSelected) }
}
@Transaction
suspend fun restoreEntriesSelection(catnums: List<Int>, isSelected: Boolean) {
suspend fun restoreSelection(catnums: List<Int>, isSelected: Boolean) {
clearEntriesSelection()
catnums.forEach { catnum -> updateEntrySelection(catnum, isSelected) }
updateSelection(catnums, isSelected)
}
@Query("UPDATE entries SET isSelected = 0")
suspend fun clearEntriesSelection()
@Transaction
suspend fun updateSelection(catnums: List<Int>, isSelected: Boolean) {
catnums.forEach { catnum -> updateEntrySelection(catnum, isSelected) }
}
@Query("UPDATE entries SET isSelected = :isSelected WHERE catnum = :catnum")
suspend fun updateEntrySelection(catnum: Int, isSelected: Boolean)
}

Wyświetl plik

@ -19,12 +19,9 @@ package com.rtbishop.look4sat.framework.local
import com.rtbishop.look4sat.data.LocalDataSource
import com.rtbishop.look4sat.domain.model.SatEntry
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.domain.predict.Satellite
import com.rtbishop.look4sat.domain.model.Transmitter
import com.rtbishop.look4sat.framework.DataMapper
import com.rtbishop.look4sat.framework.*
import com.rtbishop.look4sat.framework.model.Source
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class LocalSource(
@ -33,45 +30,31 @@ class LocalSource(
private val transmittersDao: TransmittersDao
) : LocalDataSource {
// Entries
override fun getEntriesWithModes(): Flow<List<SatItem>> {
return entriesDao.getSatItems().map { satItems ->
DataMapper.satItemsToDomainItems(satItems)
}
override fun getSatelliteItems() = entriesDao.getSatelliteItems().map { it.toDomainItems() }
override suspend fun getSelectedSatellites() = entriesDao.getSelectedSatellites().map { entry ->
entry.tle.createSat()
}
override suspend fun getSelectedSatellites(): List<Satellite> {
return entriesDao.getSelectedSatellites().map { it.tle.createSat() }
override suspend fun getTransmitters(catnum: Int): List<Transmitter> {
return transmittersDao.getTransmitters(catnum).toDomain()
}
override suspend fun getWebSources() = sourcesDao.getSources()
override suspend fun updateEntries(entries: List<SatEntry>) {
val satEntries = entries.map { entry -> DataMapper.domainEntryToSatEntry(entry) }
entriesDao.updateEntries(satEntries)
entriesDao.updateEntries(entries.toFrameworkEntries())
}
override suspend fun updateEntriesSelection(catnums: List<Int>, isSelected: Boolean) {
entriesDao.updateEntriesSelection(catnums, isSelected)
}
// Sources
override suspend fun getSources(): List<String> {
return sourcesDao.getSources()
}
override suspend fun updateSources(sources: List<String>) {
sourcesDao.deleteSources()
sourcesDao.updateSources(sources.map { Source(it) })
}
// Transmitters
override fun getTransmitters(catnum: Int): Flow<List<Transmitter>> {
return transmittersDao.getTransmitters(catnum).map { satTransList ->
DataMapper.satTransListToDomainTransList(satTransList)
}
override suspend fun updateSelection(catnums: List<Int>, isSelected: Boolean) {
entriesDao.updateSelection(catnums, isSelected)
}
override suspend fun updateTransmitters(transmitters: List<Transmitter>) {
val transList = DataMapper.domainTransListToSatTransList(transmitters)
transmittersDao.updateTransmitters(transList)
transmittersDao.updateTransmitters(transmitters.toFramework())
}
override suspend fun updateWebSources(sources: List<String>) {
sourcesDao.updateSources(sources.map { Source(it) })
}
}

Wyświetl plik

@ -26,7 +26,7 @@ import com.rtbishop.look4sat.framework.model.SatEntry
import com.rtbishop.look4sat.framework.model.Transmitter
@Database(
entities = [SatEntry::class, Transmitter::class, Source::class],
entities = [SatEntry::class, Source::class, Transmitter::class],
version = 4,
exportSchema = true
)

Wyświetl plik

@ -1,8 +1,24 @@
/*
* 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.local
import androidx.room.*
import com.rtbishop.look4sat.framework.model.Source
import com.rtbishop.look4sat.framework.model.Transmitter
@Dao
interface SourcesDao {

Wyświetl plik

@ -1,14 +1,30 @@
/*
* 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.local
import androidx.room.*
import com.rtbishop.look4sat.framework.model.Transmitter
import kotlinx.coroutines.flow.Flow
@Dao
interface TransmittersDao {
@Query("SELECT * FROM transmitters WHERE catnum = :catnum")
fun getTransmitters(catnum: Int): Flow<List<Transmitter>>
suspend fun getTransmitters(catnum: Int): List<Transmitter>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun updateTransmitters(transmitters: List<Transmitter>)

Wyświetl plik

@ -19,7 +19,7 @@ package com.rtbishop.look4sat.framework.remote
import com.rtbishop.look4sat.data.RemoteDataSource
import com.rtbishop.look4sat.domain.model.Transmitter
import com.rtbishop.look4sat.framework.DataMapper
import com.rtbishop.look4sat.framework.toDomain
import java.io.InputStream
class RemoteSource(private val satelliteApi: SatelliteApi) : RemoteDataSource {
@ -29,6 +29,6 @@ class RemoteSource(private val satelliteApi: SatelliteApi) : RemoteDataSource {
}
override suspend fun fetchTransmitters(): List<Transmitter> {
return DataMapper.satTransListToDomainTransList(satelliteApi.fetchTransmitters())
return satelliteApi.fetchTransmitters().toDomain()
}
}

Wyświetl plik

@ -21,9 +21,9 @@ import android.content.Context
import androidx.room.Room
import com.rtbishop.look4sat.data.LocalDataSource
import com.rtbishop.look4sat.data.RemoteDataSource
import com.rtbishop.look4sat.data.DataRepository
import com.rtbishop.look4sat.data.DefaultRepository
import com.rtbishop.look4sat.framework.remote.SatelliteApi
import com.rtbishop.look4sat.domain.SatelliteRepo
import com.rtbishop.look4sat.domain.DataRepository
import com.rtbishop.look4sat.domain.DataReporter
import com.rtbishop.look4sat.domain.predict.Predictor
import com.rtbishop.look4sat.framework.remote.RemoteSource
@ -65,8 +65,8 @@ object CoreModule {
localSource: LocalDataSource,
remoteSource: RemoteDataSource,
@IoDispatcher dispatcher: CoroutineDispatcher
): SatelliteRepo {
return DataRepository(localSource, remoteSource, dispatcher)
): DataRepository {
return DefaultRepository(localSource, remoteSource, dispatcher)
}
@Provides

Wyświetl plik

@ -29,7 +29,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.databinding.FragmentEntriesBinding
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.domain.DataState
import com.rtbishop.look4sat.domain.model.DataState
import com.rtbishop.look4sat.presentation.ItemDivider
import com.rtbishop.look4sat.presentation.getNavResult
import com.rtbishop.look4sat.presentation.navigateSafe
@ -42,7 +42,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.updateEntriesFromFile(uri) }
uri?.let { viewModel.updateDataFromFile(uri) }
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -51,11 +51,7 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) {
}
private fun setupComponents(view: View) {
val entriesAdapter = EntriesAdapter(object : EntriesAdapter.EntriesClickListener {
override fun updateSelection(catNums: List<Int>, isSelected: Boolean) {
viewModel.updateSelection(catNums, isSelected)
}
})
val entriesAdapter = EntriesAdapter(viewModel)
val binding = FragmentEntriesBinding.bind(view).apply {
entriesRecycler.apply {
setHasFixedSize(true)
@ -76,7 +72,7 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) {
handleSatData(satData, binding, entriesAdapter)
})
getNavResult<List<String>>(R.id.nav_entries, "sources") { sources ->
viewModel.updateEntriesFromWeb(sources)
viewModel.updateDataFromWeb(sources)
}
}

Wyświetl plik

@ -22,8 +22,8 @@ import android.net.Uri
import android.widget.SearchView
import androidx.lifecycle.*
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.domain.DataState
import com.rtbishop.look4sat.domain.SatelliteRepo
import com.rtbishop.look4sat.domain.model.DataState
import com.rtbishop.look4sat.domain.DataRepository
import com.rtbishop.look4sat.framework.PreferencesSource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineExceptionHandler
@ -37,8 +37,8 @@ import javax.inject.Inject
class EntriesViewModel @Inject constructor(
private val preferences: PreferencesSource,
private val resolver: ContentResolver,
private val satelliteRepo: SatelliteRepo
) : ViewModel(), SearchView.OnQueryTextListener {
private val dataRepository: DataRepository
) : ViewModel(), SearchView.OnQueryTextListener, EntriesAdapter.EntriesClickListener {
private val coroutineHandler = CoroutineExceptionHandler { _, throwable ->
Timber.d(throwable)
@ -47,7 +47,7 @@ class EntriesViewModel @Inject constructor(
private val transModes = MutableLiveData(preferences.loadModesSelection())
private val currentQuery = MutableLiveData(String())
private val itemsWithModes = transModes.switchMap { modes ->
liveData { satelliteRepo.getSatItems().collect { emit(filterByModes(it, modes)) } }
liveData { dataRepository.getSatelliteItems().collect { emit(filterByModes(it, modes)) } }
}
private val itemsWithQuery = currentQuery.switchMap { query ->
itemsWithModes.map { items -> DataState.Success(filterByQuery(items, query)) }
@ -58,21 +58,21 @@ class EntriesViewModel @Inject constructor(
private var shouldSelectAll = true
val satData: LiveData<DataState<List<SatItem>>> = _satData
fun updateEntriesFromFile(uri: Uri) {
fun updateDataFromFile(uri: Uri) {
viewModelScope.launch(coroutineHandler) {
_satData.value = DataState.Loading
runCatching {
resolver.openInputStream(uri)?.use { stream ->
satelliteRepo.updateEntriesFromFile(stream)
dataRepository.updateDataFromFile(stream)
}
}.onFailure { _satData.value = DataState.Error(it) }
}
}
fun updateEntriesFromWeb(sources: List<String>) {
fun updateDataFromWeb(sources: List<String>) {
viewModelScope.launch(coroutineHandler) {
_satData.value = DataState.Loading
satelliteRepo.updateEntriesFromWeb(sources)
dataRepository.updateDataFromWeb(sources)
}
}
@ -102,8 +102,8 @@ class EntriesViewModel @Inject constructor(
return true
}
fun updateSelection(catNums: List<Int>, isSelected: Boolean) {
viewModelScope.launch { satelliteRepo.updateEntriesSelection(catNums, isSelected) }
override fun updateSelection(catNums: List<Int>, isSelected: Boolean) {
viewModelScope.launch { dataRepository.updateSelection(catNums, isSelected) }
}
private fun filterByModes(items: List<SatItem>, modes: List<String>): List<SatItem> {

Wyświetl plik

@ -19,7 +19,7 @@ package com.rtbishop.look4sat.presentation.mapScreen
import androidx.lifecycle.*
import com.rtbishop.look4sat.domain.predict.Predictor
import com.rtbishop.look4sat.domain.SatelliteRepo
import com.rtbishop.look4sat.domain.DataRepository
import com.rtbishop.look4sat.framework.PreferencesSource
import com.rtbishop.look4sat.domain.predict.GeoPos
import com.rtbishop.look4sat.domain.QthConverter
@ -33,7 +33,7 @@ import kotlin.math.min
@HiltViewModel
class MapViewModel @Inject constructor(
private val satelliteRepo: SatelliteRepo,
private val dataRepository: DataRepository,
private val predictor: Predictor,
private val preferences: PreferencesSource,
) : ViewModel() {
@ -63,7 +63,7 @@ class MapViewModel @Inject constructor(
init {
viewModelScope.launch {
satelliteRepo.getSelectedSatellites().also { selectedSatellites ->
dataRepository.getSelectedSatellites().also { selectedSatellites ->
if (selectedSatellites.isNotEmpty()) {
allSatList = selectedSatellites
selectSatellite(selectedSatellites.first())

Wyświetl plik

@ -30,7 +30,7 @@ import androidx.recyclerview.widget.SimpleItemAnimator
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.databinding.FragmentPassesBinding
import com.rtbishop.look4sat.domain.predict.SatPass
import com.rtbishop.look4sat.domain.DataState
import com.rtbishop.look4sat.domain.model.DataState
import com.rtbishop.look4sat.presentation.ItemDivider
import com.rtbishop.look4sat.presentation.navigateSafe
import com.rtbishop.look4sat.presentation.toTimerString

Wyświetl plik

@ -23,8 +23,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.rtbishop.look4sat.domain.predict.Predictor
import com.rtbishop.look4sat.domain.predict.SatPass
import com.rtbishop.look4sat.domain.DataState
import com.rtbishop.look4sat.domain.SatelliteRepo
import com.rtbishop.look4sat.domain.model.DataState
import com.rtbishop.look4sat.domain.DataRepository
import com.rtbishop.look4sat.framework.PreferencesSource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
@ -34,7 +34,7 @@ import javax.inject.Inject
@HiltViewModel
class PassesViewModel @Inject constructor(
private val satelliteRepo: SatelliteRepo,
private val dataRepository: DataRepository,
private val predictor: Predictor,
private val preferences: PreferencesSource
) : ViewModel() {
@ -50,7 +50,7 @@ class PassesViewModel @Inject constructor(
viewModelScope.launch {
_passes.postValue(DataState.Loading)
val dateNow = Date()
val satellites = satelliteRepo.getSelectedSatellites()
val satellites = dataRepository.getSelectedSatellites()
val stationPos = preferences.loadStationPosition()
val hoursAhead = preferences.getHoursAhead()
val minElev = preferences.getMinElevation()
@ -71,15 +71,13 @@ class PassesViewModel @Inject constructor(
preferences.updatePositionFromGPS()
viewModelScope.launch {
_passes.postValue(DataState.Loading)
val defaultCatNums = listOf(43700, 25544, 25338, 28654, 33591, 40069, 27607, 24278)
val dateNow = Date()
val satellites = satelliteRepo.getSelectedSatellites()
val satellites = dataRepository.getSelectedSatellites()
val stationPos = preferences.loadStationPosition()
val hoursAhead = preferences.getHoursAhead()
val minElev = preferences.getMinElevation()
satelliteRepo.updateEntriesFromWeb(satelliteRepo.getDefaultSources())
satelliteRepo.updateEntriesSelection(defaultCatNums, true)
predictor.forceCalculation(satellites, stationPos, dateNow, hoursAhead, minElev)
dataRepository.updateDataFromWeb()
dataRepository.updateSelection(isSelected = true)
predictor.forceCalculation(satellites, stationPos, Date(), hoursAhead, minElev)
preferences.setSetupDone()
_isFirstLaunchDone.value = true
}
@ -90,7 +88,7 @@ class PassesViewModel @Inject constructor(
_passes.postValue(DataState.Loading)
passesProcessing?.cancelAndJoin()
val dateNow = Date()
val satellites = satelliteRepo.getSelectedSatellites()
val satellites = dataRepository.getSelectedSatellites()
val stationPos = preferences.loadStationPosition()
val hoursAhead = preferences.getHoursAhead()
val minElev = preferences.getMinElevation()

Wyświetl plik

@ -19,7 +19,7 @@ package com.rtbishop.look4sat.presentation.radarScreen
import androidx.lifecycle.*
import com.rtbishop.look4sat.domain.DataReporter
import com.rtbishop.look4sat.domain.SatelliteRepo
import com.rtbishop.look4sat.domain.DataRepository
import com.rtbishop.look4sat.domain.predict.Predictor
import com.rtbishop.look4sat.domain.predict.SatPass
import com.rtbishop.look4sat.domain.predict.SatPos
@ -40,7 +40,7 @@ class RadarViewModel @Inject constructor(
private val orientationSource: OrientationSource,
private val preferences: PreferencesSource,
private val predictor: Predictor,
private val satelliteRepo: SatelliteRepo,
private val dataRepository: DataRepository,
private val dataReporter: DataReporter
) : ViewModel(), OrientationSource.OrientationListener {
@ -100,21 +100,20 @@ class RadarViewModel @Inject constructor(
private fun processTransmitters(satPass: SatPass) {
viewModelScope.launch {
satelliteRepo.getTransmitters(satPass.catNum).collect { transList ->
while (isActive) {
val satPos = predictor.getSatPos(satPass.satellite, stationPos, Date())
val copiedList = transList.map { it.copy() }
copiedList.forEach { transmitter ->
transmitter.downlink?.let {
transmitter.downlink = satPos.getDownlinkFreq(it)
}
transmitter.uplink?.let {
transmitter.uplink = satPos.getUplinkFreq(it)
}
val transmitters = dataRepository.getTransmitters(satPass.catNum)
while (isActive) {
val satPos = predictor.getSatPos(satPass.satellite, stationPos, Date())
val copiedList = transmitters.map { it.copy() }
copiedList.forEach { transmitter ->
transmitter.downlink?.let {
transmitter.downlink = satPos.getDownlinkFreq(it)
}
transmitter.uplink?.let {
transmitter.uplink = satPos.getUplinkFreq(it)
}
_transmitters.postValue(copiedList.map { it.copy() })
delay(1000)
}
_transmitters.postValue(copiedList.map { it.copy() })
delay(1000)
}
}
}

Wyświetl plik

@ -2,14 +2,14 @@ package com.rtbishop.look4sat.presentation.sourcesScreen
import androidx.lifecycle.ViewModel
import androidx.lifecycle.liveData
import com.rtbishop.look4sat.domain.SatelliteRepo
import com.rtbishop.look4sat.domain.DataRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class SourcesViewModel @Inject constructor(satelliteRepo: SatelliteRepo) : ViewModel() {
class SourcesViewModel @Inject constructor(dataRepository: DataRepository) : ViewModel() {
val sources = liveData {
emit(satelliteRepo.getSavedSources())
emit(dataRepository.getWebSources())
}
}

Wyświetl plik

@ -17,62 +17,49 @@
*/
package com.rtbishop.look4sat.data
import com.rtbishop.look4sat.domain.SatelliteRepo
import com.rtbishop.look4sat.domain.DataRepository
import com.rtbishop.look4sat.domain.model.SatEntry
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.domain.model.Transmitter
import com.rtbishop.look4sat.domain.predict.Satellite
import com.rtbishop.look4sat.domain.predict.TLE
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.InputStream
import java.util.zip.ZipInputStream
class DataRepository(
class DefaultRepository(
private val localSource: LocalDataSource,
private val remoteSource: RemoteDataSource,
private val repoDispatcher: CoroutineDispatcher
) : SatelliteRepo {
) : DataRepository {
override fun getSatItems(): Flow<List<SatItem>> {
return localSource.getEntriesWithModes()
override val defaultSelection = listOf(43700, 25544, 25338, 28654, 33591, 40069, 27607, 24278)
override 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"
)
override fun getSatelliteItems() = localSource.getSatelliteItems()
override suspend fun getSelectedSatellites() = localSource.getSelectedSatellites()
override suspend fun getTransmitters(catnum: Int) = localSource.getTransmitters(catnum)
override suspend fun getWebSources() = localSource.getWebSources().also { sources ->
return if (sources.isNotEmpty()) sources
else defaultSources
}
override fun getTransmitters(catnum: Int): Flow<List<Transmitter>> {
return localSource.getTransmitters(catnum)
override suspend fun updateDataFromFile(stream: InputStream) = withContext(repoDispatcher) {
localSource.updateEntries(importSatellites(stream))
}
override fun getDefaultSources(): List<String> {
return 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"
)
}
override suspend fun getSavedSources(): List<String> {
val savedSources = localSource.getSources()
return if (savedSources.isEmpty()) {
getDefaultSources()
} else savedSources
}
override suspend fun getSelectedSatellites(): List<Satellite> {
return localSource.getSelectedSatellites()
}
override suspend fun updateEntriesFromFile(stream: InputStream) = withContext(repoDispatcher) {
localSource.updateEntries(importSatEntries(stream))
}
override suspend fun updateEntriesFromWeb(sources: List<String>) {
override suspend fun updateDataFromWeb(sources: List<String>) {
coroutineScope {
launch(repoDispatcher) {
localSource.updateSources(sources)
localSource.updateWebSources(sources)
}
launch(repoDispatcher) {
val streams = mutableListOf<InputStream>()
@ -87,7 +74,7 @@ class DataRepository(
}
}
}
streams.forEach { stream -> entries.addAll(importSatEntries(stream)) }
streams.forEach { stream -> entries.addAll(importSatellites(stream)) }
localSource.updateEntries(entries)
}
launch(repoDispatcher) {
@ -97,11 +84,11 @@ class DataRepository(
}
}
override suspend fun updateEntriesSelection(catnums: List<Int>, isSelected: Boolean) {
localSource.updateEntriesSelection(catnums, isSelected)
override suspend fun updateSelection(catnums: List<Int>, isSelected: Boolean) {
localSource.updateSelection(catnums, isSelected)
}
private fun importSatEntries(stream: InputStream): List<SatEntry> {
private fun importSatellites(stream: InputStream): List<SatEntry> {
return TLE.parseTleStream(stream).map { tle -> SatEntry(tle) }
}
}

Wyświetl plik

@ -25,22 +25,19 @@ import kotlinx.coroutines.flow.Flow
interface LocalDataSource {
// Entries
fun getEntriesWithModes(): Flow<List<SatItem>>
fun getSatelliteItems(): Flow<List<SatItem>>
suspend fun getSelectedSatellites(): List<Satellite>
suspend fun getTransmitters(catnum: Int): List<Transmitter>
suspend fun getWebSources(): List<String>
suspend fun updateEntries(entries: List<SatEntry>)
suspend fun updateEntriesSelection(catnums: List<Int>, isSelected: Boolean)
// Sources
suspend fun getSources(): List<String>
suspend fun updateSources(sources: List<String>)
// Transmitters
fun getTransmitters(catnum: Int): Flow<List<Transmitter>>
suspend fun updateSelection(catnums: List<Int>, isSelected: Boolean)
suspend fun updateTransmitters(transmitters: List<Transmitter>)
suspend fun updateWebSources(sources: List<String>)
}

Wyświetl plik

@ -23,21 +23,22 @@ import com.rtbishop.look4sat.domain.predict.Satellite
import kotlinx.coroutines.flow.Flow
import java.io.InputStream
interface SatelliteRepo {
interface DataRepository {
fun getSatItems(): Flow<List<SatItem>>
val defaultSelection: List<Int>
val defaultSources: List<String>
fun getTransmitters(catnum: Int): Flow<List<Transmitter>>
fun getDefaultSources(): List<String>
suspend fun getSavedSources(): List<String>
fun getSatelliteItems(): Flow<List<SatItem>>
suspend fun getSelectedSatellites(): List<Satellite>
suspend fun updateEntriesFromFile(stream: InputStream)
suspend fun getTransmitters(catnum: Int): List<Transmitter>
suspend fun updateEntriesFromWeb(sources: List<String>)
suspend fun getWebSources(): List<String>
suspend fun updateEntriesSelection(catnums: List<Int>, isSelected: Boolean)
suspend fun updateDataFromFile(stream: InputStream)
suspend fun updateDataFromWeb(sources: List<String> = defaultSources)
suspend fun updateSelection(catnums: List<Int> = defaultSelection, isSelected: Boolean = true)
}

Wyświetl plik

@ -15,7 +15,7 @@
* 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.domain
package com.rtbishop.look4sat.domain.model
sealed class DataState<out T> {
data class Success<out T>(val data: T) : DataState<T>()

Wyświetl plik

@ -20,4 +20,3 @@ android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
kapt.use.worker.api=false
org.gradle.unsafe.configuration-cache=true