Moved DataSources storage to SharedPreferences

pull/87/head
Arty Bishop 2021-12-31 18:50:41 +00:00
rodzic 0f4a70b204
commit 9c137ada9f
16 zmienionych plików z 108 dodań i 656 usunięć

Wyświetl plik

@ -26,15 +26,8 @@ android {
}
}
// def props = new Properties()
// file("../securityKeys.properties").withInputStream { props.load(it) }
buildTypes {
release {
// buildConfigField "String", "ApiKey", props.getProperty("apiKey")
// minifyEnabled true
// shrinkResources true
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
postprocessing {
removeUnusedCode true
removeUnusedResources true

Wyświetl plik

@ -1,21 +0,0 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

Wyświetl plik

@ -1,134 +0,0 @@
{
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "555494c464b5a29285eb5493cc8aa5f6",
"entities": [
{
"tableName": "entries",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tle` TEXT NOT NULL, `catNum` INTEGER NOT NULL, `name` TEXT NOT NULL, `isSelected` INTEGER NOT NULL, PRIMARY KEY(`catNum`))",
"fields": [
{
"fieldPath": "tle",
"columnName": "tle",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "catNum",
"columnName": "catNum",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isSelected",
"columnName": "isSelected",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"catNum"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "transmitters",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `info` TEXT NOT NULL, `isAlive` INTEGER NOT NULL, `downlink` INTEGER, `uplink` INTEGER, `mode` TEXT, `isInverted` INTEGER NOT NULL, `catNum` INTEGER, PRIMARY KEY(`uuid`))",
"fields": [
{
"fieldPath": "uuid",
"columnName": "uuid",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "info",
"columnName": "info",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isAlive",
"columnName": "isAlive",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "downlink",
"columnName": "downlink",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "uplink",
"columnName": "uplink",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "mode",
"columnName": "mode",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "isInverted",
"columnName": "isInverted",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "catNum",
"columnName": "catNum",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"uuid"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "sources",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceUrl` TEXT NOT NULL, PRIMARY KEY(`sourceUrl`))",
"fields": [
{
"fieldPath": "sourceUrl",
"columnName": "sourceUrl",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"sourceUrl"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '555494c464b5a29285eb5493cc8aa5f6')"
]
}
}

Wyświetl plik

@ -1,134 +0,0 @@
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "555494c464b5a29285eb5493cc8aa5f6",
"entities": [
{
"tableName": "entries",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tle` TEXT NOT NULL, `catNum` INTEGER NOT NULL, `name` TEXT NOT NULL, `isSelected` INTEGER NOT NULL, PRIMARY KEY(`catNum`))",
"fields": [
{
"fieldPath": "tle",
"columnName": "tle",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "catNum",
"columnName": "catNum",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isSelected",
"columnName": "isSelected",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"catNum"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "transmitters",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `info` TEXT NOT NULL, `isAlive` INTEGER NOT NULL, `downlink` INTEGER, `uplink` INTEGER, `mode` TEXT, `isInverted` INTEGER NOT NULL, `catNum` INTEGER, PRIMARY KEY(`uuid`))",
"fields": [
{
"fieldPath": "uuid",
"columnName": "uuid",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "info",
"columnName": "info",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isAlive",
"columnName": "isAlive",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "downlink",
"columnName": "downlink",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "uplink",
"columnName": "uplink",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "mode",
"columnName": "mode",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "isInverted",
"columnName": "isInverted",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "catNum",
"columnName": "catNum",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"uuid"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "sources",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceUrl` TEXT NOT NULL, PRIMARY KEY(`sourceUrl`))",
"fields": [
{
"fieldPath": "sourceUrl",
"columnName": "sourceUrl",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"sourceUrl"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '555494c464b5a29285eb5493cc8aa5f6')"
]
}
}

Wyświetl plik

@ -1,212 +0,0 @@
{
"formatVersion": 1,
"database": {
"version": 4,
"identityHash": "0f08defa24a78647801005e9277faac7",
"entities": [
{
"tableName": "entries",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`isSelected` INTEGER NOT NULL, `name` TEXT NOT NULL, `epoch` REAL NOT NULL, `meanmo` REAL NOT NULL, `eccn` REAL NOT NULL, `incl` REAL NOT NULL, `raan` REAL NOT NULL, `argper` REAL NOT NULL, `meanan` REAL NOT NULL, `catnum` INTEGER NOT NULL, `bstar` REAL NOT NULL, `xincl` REAL NOT NULL, `xnodeo` REAL NOT NULL, `omegao` REAL NOT NULL, `xmo` REAL NOT NULL, `xno` REAL NOT NULL, `isDeepspace` INTEGER NOT NULL, PRIMARY KEY(`catnum`))",
"fields": [
{
"fieldPath": "isSelected",
"columnName": "isSelected",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "tle.name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "tle.epoch",
"columnName": "epoch",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.meanmo",
"columnName": "meanmo",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.eccn",
"columnName": "eccn",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.incl",
"columnName": "incl",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.raan",
"columnName": "raan",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.argper",
"columnName": "argper",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.meanan",
"columnName": "meanan",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.catnum",
"columnName": "catnum",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "tle.bstar",
"columnName": "bstar",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.xincl",
"columnName": "xincl",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.xnodeo",
"columnName": "xnodeo",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.omegao",
"columnName": "omegao",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.xmo",
"columnName": "xmo",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.xno",
"columnName": "xno",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "tle.isDeepspace",
"columnName": "isDeepspace",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"catnum"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "transmitters",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `info` TEXT NOT NULL, `isAlive` INTEGER NOT NULL, `downlink` INTEGER, `uplink` INTEGER, `mode` TEXT, `isInverted` INTEGER NOT NULL, `catnum` INTEGER, PRIMARY KEY(`uuid`))",
"fields": [
{
"fieldPath": "uuid",
"columnName": "uuid",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "info",
"columnName": "info",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isAlive",
"columnName": "isAlive",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "downlink",
"columnName": "downlink",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "uplink",
"columnName": "uplink",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "mode",
"columnName": "mode",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "isInverted",
"columnName": "isInverted",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "catnum",
"columnName": "catnum",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"uuid"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "sources",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceUrl` TEXT NOT NULL, PRIMARY KEY(`sourceUrl`))",
"fields": [
{
"fieldPath": "sourceUrl",
"columnName": "sourceUrl",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"sourceUrl"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '0f08defa24a78647801005e9277faac7')"
]
}
}

Wyświetl plik

@ -22,6 +22,7 @@ import android.hardware.GeomagneticField
import android.location.LocationManager
import androidx.core.content.edit
import com.rtbishop.look4sat.BuildConfig
import com.rtbishop.look4sat.data.PreferencesHandler
import com.rtbishop.look4sat.domain.QthConverter
import com.rtbishop.look4sat.domain.predict.GeoPos
import com.rtbishop.look4sat.presentation.round
@ -32,11 +33,12 @@ import javax.inject.Singleton
class PreferencesSource @Inject constructor(
private val locationManager: LocationManager,
private val preferences: SharedPreferences
) {
) : PreferencesHandler {
private val keyInitialSetup = "${BuildConfig.VERSION_NAME}update"
companion object {
const val keyDataSources = "dataSources"
const val keyModes = "satModes"
const val keyCompass = "compass"
const val keyRadarSweep = "radarSweep"
@ -184,4 +186,13 @@ class PreferencesSource @Inject constructor(
fun setRotatorPort(value: String) {
preferences.edit { putString(keyRotatorPort, value) }
}
override fun loadDataSources(): List<String> {
val sourcesList = preferences.getStringSet(keyDataSources, null)?.toList()
return if (sourcesList.isNullOrEmpty()) defaultSources else sourcesList
}
override fun saveDataSources(sources: List<String>) {
if (sources.isNotEmpty()) preferences.edit { putStringSet(keyDataSources, sources.toSet()) }
}
}

Wyświetl plik

@ -22,14 +22,15 @@ 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.framework.*
import com.rtbishop.look4sat.framework.model.Source
import com.rtbishop.look4sat.framework.toDomain
import com.rtbishop.look4sat.framework.toDomainItems
import com.rtbishop.look4sat.framework.toFramework
import com.rtbishop.look4sat.framework.toFrameworkEntries
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class LocalSource(
private val entriesDao: EntriesDao,
private val sourcesDao: SourcesDao,
private val transmittersDao: TransmittersDao
) : LocalDataSource {
@ -41,8 +42,6 @@ class LocalSource(
return entriesDao.getSelectedSatellites().map { entry -> entry.tle.createSat() }
}
override suspend fun getSources() = sourcesDao.getSources()
override suspend fun getTransmitters(catnum: Int): List<Transmitter> {
return transmittersDao.getTransmitters(catnum).toDomain()
}
@ -55,10 +54,6 @@ class LocalSource(
entriesDao.updateEntriesSelection(catnums, isSelected)
}
override suspend fun updateSources(sources: List<String>) {
sourcesDao.updateSources(sources.map { sourceUrl -> Source(sourceUrl) })
}
override suspend fun updateTransmitters(transmitters: List<Transmitter>) {
transmittersDao.updateTransmitters(transmitters.toFramework())
}

Wyświetl plik

@ -19,50 +19,13 @@ package com.rtbishop.look4sat.framework.local
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.rtbishop.look4sat.framework.model.Source
import com.rtbishop.look4sat.framework.model.SatEntry
import com.rtbishop.look4sat.framework.model.Transmitter
@Database(
entities = [SatEntry::class, Source::class, Transmitter::class],
version = 4,
exportSchema = true
)
@Database(entities = [SatEntry::class, Transmitter::class], version = 1)
abstract class SatelliteDb : RoomDatabase() {
abstract fun entriesDao(): EntriesDao
abstract fun sourcesDao(): SourcesDao
abstract fun transmittersDao(): TransmittersDao
}
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE trans_backup (uuid TEXT NOT NULL, info TEXT NOT NULL, isAlive INTEGER NOT NULL, downlink INTEGER, uplink INTEGER, mode TEXT, isInverted INTEGER NOT NULL, catNum INTEGER, PRIMARY KEY(uuid))")
database.execSQL("INSERT INTO trans_backup (uuid, info, isAlive, downlink, uplink, mode, isInverted, catNum) SELECT uuid, info, isAlive, downlink, uplink, mode, isInverted, catNum FROM transmitters")
database.execSQL("DROP TABLE transmitters")
database.execSQL("ALTER TABLE trans_backup RENAME TO transmitters")
}
}
val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE sources (sourceUrl TEXT NOT NULL, PRIMARY KEY(sourceUrl))")
}
}
val MIGRATION_3_4 = object : Migration(3, 4) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE entries_backup (isSelected INTEGER NOT NULL, name TEXT NOT NULL, epoch REAL NOT NULL, meanmo REAL NOT NULL, eccn REAL NOT NULL, incl REAL NOT NULL, raan REAL NOT NULL, argper REAL NOT NULL, meanan REAL NOT NULL, catnum INTEGER NOT NULL, bstar REAL NOT NULL, xincl REAL NOT NULL, xnodeo REAL NOT NULL, omegao REAL NOT NULL, xmo REAL NOT NULL, xno REAL NOT NULL, isDeepspace INTEGER NOT NULL, PRIMARY KEY(catnum))")
database.execSQL("INSERT INTO entries_backup (isSelected, name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar, xincl, xnodeo, omegao, xmo, xno, isDeepspace) SELECT isSelected, 'name', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, catNum, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0 FROM entries")
database.execSQL("DROP TABLE entries")
database.execSQL("ALTER TABLE entries_backup RENAME TO entries")
database.execSQL("CREATE TABLE trans_backup (uuid TEXT NOT NULL, info TEXT NOT NULL, isAlive INTEGER NOT NULL, downlink INTEGER, uplink INTEGER, mode TEXT, isInverted INTEGER NOT NULL, catnum INTEGER, PRIMARY KEY(uuid))")
database.execSQL("INSERT INTO trans_backup (uuid, info, isAlive, downlink, uplink, mode, isInverted, catnum) SELECT uuid, info, isAlive, downlink, uplink, mode, isInverted, catNum FROM transmitters")
database.execSQL("DROP TABLE transmitters")
database.execSQL("ALTER TABLE trans_backup RENAME TO transmitters")
}
}

Wyświetl plik

@ -18,13 +18,18 @@
package com.rtbishop.look4sat.injection
import android.content.Context
import android.content.SharedPreferences
import android.location.LocationManager
import androidx.room.Room
import com.rtbishop.look4sat.data.DefaultRepository
import com.rtbishop.look4sat.data.PreferencesHandler
import com.rtbishop.look4sat.domain.DataParser
import com.rtbishop.look4sat.domain.DataRepository
import com.rtbishop.look4sat.domain.DataReporter
import com.rtbishop.look4sat.domain.DataRepository
import com.rtbishop.look4sat.domain.predict.Predictor
import com.rtbishop.look4sat.framework.local.*
import com.rtbishop.look4sat.framework.PreferencesSource
import com.rtbishop.look4sat.framework.local.LocalSource
import com.rtbishop.look4sat.framework.local.SatelliteDb
import com.rtbishop.look4sat.framework.remote.RemoteSource
import dagger.Module
import dagger.Provides
@ -41,16 +46,26 @@ object CoreModule {
@Provides
@Singleton
fun provideSatelliteRepo(
preferencesHandler: PreferencesHandler,
@ApplicationContext context: Context,
@IoDispatcher ioDispatcher: CoroutineDispatcher,
@DefaultDispatcher defaultDispatcher: CoroutineDispatcher
): DataRepository {
val dataParser = DataParser(defaultDispatcher)
val db = Room.databaseBuilder(context, SatelliteDb::class.java, "SatelliteDb")
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4).build()
val localSource = LocalSource(db.entriesDao(), db.sourcesDao(), db.transmittersDao())
.fallbackToDestructiveMigration().build()
val localSource = LocalSource(db.entriesDao(), db.transmittersDao())
val remoteSource = RemoteSource(ioDispatcher)
return DefaultRepository(dataParser, localSource, remoteSource)
return DefaultRepository(dataParser, localSource, remoteSource, preferencesHandler)
}
@Provides
@Singleton
fun providePreferencesHandler(
locationManager: LocationManager,
sharedPreferences: SharedPreferences
): PreferencesHandler {
return PreferencesSource(locationManager, sharedPreferences)
}
@Provides

Wyświetl plik

@ -84,14 +84,6 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
passesSettings.setOnClickListener { findNavController().navigate(R.id.nav_prefs) }
passesFab.setOnClickListener { findNavController().navigate(R.id.nav_entries) }
}
// val appBarConfiguration = AppBarConfiguration(setOf(R.id.nav_passes))
// binding.passesToolbar.setupWithNavController(findNavController(), appBarConfiguration)
// binding.passesToolbar.navigationIcon =
// ResourcesCompat.getDrawable(resources, R.drawable.ic_add, requireActivity().theme)
// binding.passesToolbar.inflateMenu(R.menu.passes_menu)
// binding.passesFab.setOnClickListener {
// findNavController().navigate(R.id.nav_entries)
// }
passesViewModel.passes.observe(viewLifecycleOwner, { passesResult ->
handleNewPasses(passesResult, passesAdapter, binding)
})

Wyświetl plik

@ -28,7 +28,6 @@ import com.rtbishop.look4sat.domain.predict.SatPass
import com.rtbishop.look4sat.framework.PreferencesSource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
import java.util.*
import javax.inject.Inject
@HiltViewModel
@ -38,7 +37,7 @@ class PassesViewModel @Inject constructor(
private val preferences: PreferencesSource
) : ViewModel() {
private val _passes = MutableLiveData<DataState<List<SatPass>>>(DataState.Loading)
private val _passes = MutableLiveData<DataState<List<SatPass>>>()
private val _isFirstLaunchDone = MutableLiveData<Boolean>()
private var passesProcessing: Job? = null
val passes: LiveData<DataState<List<SatPass>>> = _passes
@ -69,15 +68,15 @@ class PassesViewModel @Inject constructor(
fun triggerInitialSetup() {
preferences.updatePositionFromGPS()
viewModelScope.launch {
_passes.postValue(DataState.Loading)
val satellites = dataRepository.getSelectedSatellites()
val stationPos = preferences.loadStationPosition()
val hoursAhead = preferences.getHoursAhead()
val minElev = preferences.getMinElevation()
dataRepository.updateDataFromWeb()
dataRepository.updateSelection(isSelected = true)
predictor.forceCalculation(satellites, stationPos, Date().time, hoursAhead, minElev)
preferences.setSetupDone()
// _passes.postValue(DataState.Loading)
// val satellites = dataRepository.getSelectedSatellites()
// val stationPos = preferences.loadStationPosition()
// val hoursAhead = preferences.getHoursAhead()
// val minElev = preferences.getMinElevation()
// dataRepository.updateDataFromWeb()
// dataRepository.updateSelection(isSelected = true)
// predictor.forceCalculation(satellites, stationPos, Date().time, hoursAhead, minElev)
// preferences.setSetupDone()
_isFirstLaunchDone.value = true
}
}

Wyświetl plik

@ -23,22 +23,20 @@ import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.appcompat.app.AppCompatDialogFragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.data.PreferencesHandler
import com.rtbishop.look4sat.databinding.DialogSourcesBinding
import com.rtbishop.look4sat.domain.DataRepository
import com.rtbishop.look4sat.framework.model.Source
import com.rtbishop.look4sat.presentation.setNavResult
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import javax.inject.Inject
@AndroidEntryPoint
class SourcesDialog : AppCompatDialogFragment() {
@Inject
lateinit var dataRepository: DataRepository
lateinit var preferences: PreferencesHandler
override fun onCreateView(inflater: LayoutInflater, group: ViewGroup?, state: Bundle?): View? {
return inflater.inflate(R.layout.dialog_sources, group, false)
@ -46,50 +44,25 @@ class SourcesDialog : AppCompatDialogFragment() {
override fun onViewCreated(view: View, state: Bundle?) {
super.onViewCreated(view, state)
// liveData { emit(dataRepository.getWebSources()) }.observe(viewLifecycleOwner, { sources ->
// val sourcesAdapter = SourcesAdapter().apply { setSources(sources.map { Source(it) }) }
// DialogSourcesBinding.bind(view).apply {
// dialog?.window?.setLayout(
// WindowManager.LayoutParams.MATCH_PARENT,
// WindowManager.LayoutParams.WRAP_CONTENT
// )
// sourcesRecycler.apply {
// adapter = sourcesAdapter
// layoutManager = LinearLayoutManager(requireContext())
// }
// sourcesBtnAdd.setOnClickListener {
// sourcesAdapter.addSource()
// }
// sourcesBtnPos.setOnClickListener {
// setNavResult("sources", sourcesAdapter.getSources().map { it.sourceUrl })
// dismiss()
// }
// sourcesBtnNeg.setOnClickListener { dismiss() }
// }
// })
lifecycleScope.launch {
val sources = dataRepository.getWebSources()
val sourcesAdapter = SourcesAdapter()
DialogSourcesBinding.bind(view).apply {
dialog?.window?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT
)
sourcesRecycler.apply {
sourcesAdapter.apply { setSources(sources.map { Source(it) }) }
adapter = sourcesAdapter
layoutManager = LinearLayoutManager(requireContext())
}
sourcesBtnAdd.setOnClickListener {
sourcesAdapter.addSource()
}
sourcesBtnPos.setOnClickListener {
setNavResult("sources", sourcesAdapter.getSources().map { it.sourceUrl })
dismiss()
}
sourcesBtnNeg.setOnClickListener { dismiss() }
val sources = preferences.loadDataSources()
val sourcesAdapter = SourcesAdapter().apply { setSources(sources.map { Source(it) }) }
DialogSourcesBinding.bind(view).apply {
dialog?.window?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT
)
sourcesRecycler.apply {
adapter = sourcesAdapter
layoutManager = LinearLayoutManager(requireContext())
}
sourcesBtnAdd.setOnClickListener {
sourcesAdapter.addSource()
}
sourcesBtnPos.setOnClickListener {
setNavResult("sources", sourcesAdapter.getSources().map { it.sourceUrl })
dismiss()
}
sourcesBtnNeg.setOnClickListener { dismiss() }
}
}
}

Wyświetl plik

@ -31,29 +31,16 @@ import kotlin.system.measureTimeMillis
class DefaultRepository(
private val dataParser: DataParser,
private val localSource: LocalDataSource,
private val remoteSource: RemoteDataSource
private val remoteSource: RemoteDataSource,
private val preferences: PreferencesHandler
) : DataRepository {
override val defaultSelection = listOf(43700, 25544, 25338, 28654, 33591, 40069, 27607, 24278)
override val defaultSources = listOf(
"https://celestrak.com/NORAD/elements/gp.php?GROUP=active&FORMAT=csv",
"https://amsat.org/tle/current/nasabare.txt",
"https://www.prismnet.com/~mmccants/tles/classfd.zip",
"https://www.prismnet.com/~mmccants/tles/inttles.zip"
)
override val transmittersSource = "https://db.satnogs.org/api/transmitters/?format=json"
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.getSources().also { sources ->
return if (sources.isNotEmpty()) sources
else defaultSources
}
override suspend fun updateDataFromFile(stream: InputStream) {
localSource.updateEntries(importSatellites(stream))
}
@ -61,7 +48,7 @@ class DefaultRepository(
override suspend fun updateDataFromWeb(sources: List<String>) {
coroutineScope {
launch {
localSource.updateSources(sources)
preferences.saveDataSources(sources)
}
launch {
val updateTimeMillis = measureTimeMillis {
@ -91,7 +78,7 @@ class DefaultRepository(
println("Update from web took $updateTimeMillis ms")
}
launch {
remoteSource.fetchFileStream(transmittersSource)?.let { inputStream ->
remoteSource.fetchFileStream(preferences.transmittersSource)?.let { inputStream ->
val transmitters = dataParser.parseJSONStream(inputStream)
localSource.updateTransmitters(transmitters)
}

Wyświetl plik

@ -29,15 +29,11 @@ interface LocalDataSource {
suspend fun getSelectedSatellites(): List<Satellite>
suspend fun getSources(): List<String>
suspend fun getTransmitters(catnum: Int): List<Transmitter>
suspend fun updateEntries(entries: List<SatEntry>)
suspend fun updateEntriesSelection(catnums: List<Int>, isSelected: Boolean)
suspend fun updateSources(sources: List<String>)
suspend fun updateTransmitters(transmitters: List<Transmitter>)
}

Wyświetl plik

@ -0,0 +1,35 @@
/*
* 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.data
interface PreferencesHandler {
val defaultSources: List<String>
get() = listOf(
"https://celestrak.com/NORAD/elements/gp.php?GROUP=active&FORMAT=csv",
"https://amsat.org/tle/current/nasabare.txt",
"https://prismnet.com/~mmccants/tles/classfd.zip",
"https://prismnet.com/~mmccants/tles/inttles.zip"
)
val transmittersSource: String
get() = "https://db.satnogs.org/api/transmitters/?format=json"
fun loadDataSources(): List<String>
fun saveDataSources(sources: List<String>)
}

Wyświetl plik

@ -25,21 +25,15 @@ import java.io.InputStream
interface DataRepository {
val defaultSelection: List<Int>
val defaultSources: List<String>
val transmittersSource: String
fun getSatelliteItems(): Flow<List<SatItem>>
suspend fun getSelectedSatellites(): List<Satellite>
suspend fun getTransmitters(catnum: Int): List<Transmitter>
suspend fun getWebSources(): List<String>
suspend fun updateDataFromFile(stream: InputStream)
suspend fun updateDataFromWeb(sources: List<String> = defaultSources)
suspend fun updateDataFromWeb(sources: List<String>)
suspend fun updateSelection(catnums: List<Int> = defaultSelection, isSelected: Boolean = true)
suspend fun updateSelection(catnums: List<Int>, isSelected: Boolean = true)
}