kopia lustrzana https://github.com/rt-bishop/Look4Sat
Further code refactoring and cleanup
rodzic
253321f3c2
commit
bf72cd2061
|
@ -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() }
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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) })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
}
|
|
@ -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>)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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>()
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue