kopia lustrzana https://github.com/rt-bishop/Look4Sat
Moved DataSources storage to SharedPreferences
rodzic
0f4a70b204
commit
9c137ada9f
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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()) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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>)
|
||||
}
|
||||
|
|
|
@ -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>)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue