diff --git a/app/schemas/com.rtbishop.look4sat.framework.local.Look4SatDb/1.json b/app/schemas/com.rtbishop.look4sat.framework.data.StorageDb/1.json
similarity index 100%
rename from app/schemas/com.rtbishop.look4sat.framework.local.Look4SatDb/1.json
rename to app/schemas/com.rtbishop.look4sat.framework.data.StorageDb/1.json
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a1a8feeb..870b38e9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,7 +7,7 @@
.
- */
-package com.rtbishop.look4sat.framework
-
-import com.rtbishop.look4sat.domain.model.SatEntry as DomainEntry
-import com.rtbishop.look4sat.domain.model.SatItem as DomainItem
-import com.rtbishop.look4sat.domain.model.SatRadio as DomainRadio
-import com.rtbishop.look4sat.framework.model.SatEntry as FrameworkEntry
-import com.rtbishop.look4sat.framework.model.SatItem as FrameworkItem
-import com.rtbishop.look4sat.framework.model.SatRadio as FrameworkRadio
-
-fun DomainEntry.toFramework() = FrameworkEntry(this.data, this.comment)
-
-fun DomainRadio.toFramework() = FrameworkRadio(
- this.uuid, this.info, this.isAlive, this.downlink, this.uplink,
- this.mode, this.isInverted, this.catnum, this.comment
-)
-
-fun FrameworkItem.toDomain() = DomainItem(this.catnum, this.name, this.modes, false)
-
-fun FrameworkRadio.toDomain() = DomainRadio(
- this.uuid, this.info, this.isAlive, this.downlink, this.uplink,
- this.mode, this.isInverted, this.catnum, this.comment
-)
-
-fun List.toFrameworkEntries() = this.map { it.toFramework() }
-
-fun List.toFrameworkRadios() = this.map { it.toFramework() }
-
-fun List.toDomainItems() = this.map { it.toDomain() }
-
-fun List.toDomainRadios() = this.map { it.toDomain() }
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/LocationHandler.kt b/app/src/main/java/com/rtbishop/look4sat/framework/LocationHandler.kt
index 8ffdd954..3ec80fa7 100644
--- a/app/src/main/java/com/rtbishop/look4sat/framework/LocationHandler.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/framework/LocationHandler.kt
@@ -26,8 +26,8 @@ import android.location.LocationManager
import android.os.Bundle
import androidx.core.content.ContextCompat
import com.rtbishop.look4sat.R
-import com.rtbishop.look4sat.data.ISettingsHandler
import com.rtbishop.look4sat.domain.ILocationHandler
+import com.rtbishop.look4sat.domain.ISettings
import com.rtbishop.look4sat.domain.QthConverter
import com.rtbishop.look4sat.domain.model.DataState
import com.rtbishop.look4sat.domain.predict.GeoPos
@@ -41,7 +41,7 @@ import javax.inject.Singleton
@Singleton
class LocationHandler @Inject constructor(
@ApplicationContext private val context: Context,
- private val settingsHandler: ISettingsHandler,
+ private val settings: ISettings,
) : LocationListener, ILocationHandler {
private val manager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
@@ -51,8 +51,8 @@ class LocationHandler @Inject constructor(
private val locationCoarse = Manifest.permission.ACCESS_COARSE_LOCATION
private val locationFine = Manifest.permission.ACCESS_FINE_LOCATION
private val _stationPosition = MutableStateFlow>(DataState.Handled)
- private var currentLocator = settingsHandler.loadStationLocator()
- private var currentPosition = settingsHandler.loadStationPosition()
+ private var currentLocator = settings.loadStationLocator()
+ private var currentPosition = settings.loadStationPosition()
override val stationPosition: StateFlow> = _stationPosition
@@ -68,8 +68,8 @@ class LocationHandler @Inject constructor(
QthConverter.positionToQth(newLat, newLon)?.let { locator ->
currentLocator = locator
currentPosition = GeoPos(newLat, newLon)
- settingsHandler.saveStationLocator(locator)
- settingsHandler.saveStationPosition(currentPosition)
+ settings.saveStationLocator(locator)
+ settings.saveStationPosition(currentPosition)
_stationPosition.value = DataState.Success(currentPosition)
}
} else {
@@ -113,8 +113,8 @@ class LocationHandler @Inject constructor(
if (position != null) {
currentLocator = locator
currentPosition = position
- settingsHandler.saveStationLocator(locator)
- settingsHandler.saveStationPosition(currentPosition)
+ settings.saveStationLocator(locator)
+ settings.saveStationPosition(currentPosition)
_stationPosition.value = DataState.Success(currentPosition)
} else {
_stationPosition.value = DataState.Error(context.getString(R.string.pref_pos_qth_error))
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/SettingsHandler.kt b/app/src/main/java/com/rtbishop/look4sat/framework/SettingsHandler.kt
index 4ffea66a..28a8f231 100644
--- a/app/src/main/java/com/rtbishop/look4sat/framework/SettingsHandler.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/framework/SettingsHandler.kt
@@ -19,15 +19,13 @@ package com.rtbishop.look4sat.framework
import android.content.SharedPreferences
import androidx.core.content.edit
-import com.rtbishop.look4sat.data.ISettingsHandler
+import com.rtbishop.look4sat.domain.ISettings
import com.rtbishop.look4sat.domain.predict.GeoPos
-import com.rtbishop.look4sat.presentation.getDouble
-import com.rtbishop.look4sat.presentation.putDouble
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
-class SettingsHandler @Inject constructor(private val prefs: SharedPreferences) : ISettingsHandler {
+class SettingsHandler @Inject constructor(private val prefs: SharedPreferences) : ISettings {
companion object {
const val keyDataSources = "dataSources"
@@ -158,4 +156,12 @@ class SettingsHandler @Inject constructor(private val prefs: SharedPreferences)
override fun saveDataSources(sources: List) {
if (sources.isNotEmpty()) prefs.edit { putStringSet(keyDataSources, sources.toSet()) }
}
+
+ private fun SharedPreferences.getDouble(key: String, default: Double): Double {
+ return Double.fromBits(getLong(key, default.toRawBits()))
+ }
+
+ private fun SharedPreferences.Editor.putDouble(key: String, double: Double) {
+ putLong(key, double.toRawBits())
+ }
}
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/local/SatEntriesDao.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/EntriesDao.kt
similarity index 84%
rename from app/src/main/java/com/rtbishop/look4sat/framework/local/SatEntriesDao.kt
rename to app/src/main/java/com/rtbishop/look4sat/framework/data/EntriesDao.kt
index 5380d995..e323aa01 100644
--- a/app/src/main/java/com/rtbishop/look4sat/framework/local/SatEntriesDao.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/EntriesDao.kt
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package com.rtbishop.look4sat.framework.local
+package com.rtbishop.look4sat.framework.data
import androidx.room.*
import com.rtbishop.look4sat.framework.model.SatEntry
@@ -23,18 +23,18 @@ import com.rtbishop.look4sat.framework.model.SatItem
import kotlinx.coroutines.flow.Flow
@Dao
-interface SatEntriesDao {
+interface EntriesDao {
@Query("SELECT COUNT(*) FROM entries")
- fun getEntriesNumber(): Flow
+ fun getEntriesTotal(): Flow
@Transaction
@Query("SELECT catnum, name FROM entries ORDER BY name ASC")
suspend fun getEntriesWithModes(): List
@Transaction
- @Query("SELECT * FROM entries WHERE catnum IN (:catnums)")
- suspend fun getSelectedEntries(catnums: List): List
+ @Query("SELECT * FROM entries WHERE catnum IN (:selectedIds)")
+ suspend fun getEntriesWithIds(selectedIds: List): List
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertEntries(entries: List)
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/Provider.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/Provider.kt
new file mode 100644
index 00000000..2532ab53
--- /dev/null
+++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/Provider.kt
@@ -0,0 +1,25 @@
+package com.rtbishop.look4sat.framework.data
+
+import android.content.ContentResolver
+import android.net.Uri
+import com.rtbishop.look4sat.data.IProvider
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+import java.io.InputStream
+import java.net.URL
+
+class Provider(
+ private val contentResolver: ContentResolver,
+ private val ioDispatcher: CoroutineDispatcher
+) : IProvider {
+
+ @Suppress("BlockingMethodInNonBlockingContext")
+ override suspend fun getLocalFileStream(uri: String): InputStream? {
+ return withContext(ioDispatcher) { contentResolver.openInputStream(Uri.parse(uri)) }
+ }
+
+ @Suppress("BlockingMethodInNonBlockingContext")
+ override suspend fun getRemoteFileStream(url: String): InputStream? {
+ return withContext(ioDispatcher) { URL(url).openStream() }
+ }
+}
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/local/SatRadiosDao.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/RadiosDao.kt
similarity index 75%
rename from app/src/main/java/com/rtbishop/look4sat/framework/local/SatRadiosDao.kt
rename to app/src/main/java/com/rtbishop/look4sat/framework/data/RadiosDao.kt
index 1f21416e..ff939695 100644
--- a/app/src/main/java/com/rtbishop/look4sat/framework/local/SatRadiosDao.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/RadiosDao.kt
@@ -15,23 +15,21 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package com.rtbishop.look4sat.framework.local
+package com.rtbishop.look4sat.framework.data
-import androidx.room.Dao
-import androidx.room.Insert
-import androidx.room.OnConflictStrategy
-import androidx.room.Query
+import androidx.room.*
import com.rtbishop.look4sat.framework.model.SatRadio
import kotlinx.coroutines.flow.Flow
@Dao
-interface SatRadiosDao {
+interface RadiosDao {
@Query("SELECT COUNT(*) FROM radios")
- fun getRadiosNumber(): Flow
+ fun getRadiosTotal(): Flow
- @Query("SELECT * FROM radios WHERE catnum = :catnum AND isAlive = 1")
- suspend fun getRadios(catnum: Int): List
+ @Transaction
+ @Query("SELECT * FROM radios WHERE catnum = :id AND isAlive = 1")
+ suspend fun getRadiosWithId(id: Int): List
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertRadios(radios: List)
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/Storage.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/Storage.kt
new file mode 100644
index 00000000..5fad5611
--- /dev/null
+++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/Storage.kt
@@ -0,0 +1,86 @@
+/*
+ * 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 .
+ */
+package com.rtbishop.look4sat.framework.data
+
+import com.rtbishop.look4sat.data.IStorage
+import com.rtbishop.look4sat.domain.predict.Satellite
+import com.rtbishop.look4sat.domain.model.SatEntry as DomainEntry
+import com.rtbishop.look4sat.domain.model.SatItem as DomainItem
+import com.rtbishop.look4sat.domain.model.SatRadio as DomainRadio
+import com.rtbishop.look4sat.framework.model.SatEntry as FrameworkEntry
+import com.rtbishop.look4sat.framework.model.SatItem as FrameworkItem
+import com.rtbishop.look4sat.framework.model.SatRadio as FrameworkRadio
+
+class Storage(private val entriesDao: EntriesDao, private val radiosDao: RadiosDao) : IStorage {
+
+ override fun getEntriesTotal() = entriesDao.getEntriesTotal()
+
+ override fun getRadiosTotal() = radiosDao.getRadiosTotal()
+
+ override suspend fun getEntriesWithModes(): List {
+ return entriesDao.getEntriesWithModes().toDomainItems()
+ }
+
+ override suspend fun getEntriesWithIds(ids: List): List {
+ val selectedSatellites = mutableListOf()
+ ids.chunked(999).forEach { idsPart ->
+ val entries = entriesDao.getEntriesWithIds(idsPart)
+ selectedSatellites.addAll(entries.map { entry -> entry.data.createSat() })
+ }
+ return selectedSatellites
+ }
+
+ override suspend fun getRadiosWithId(id: Int): List {
+ return radiosDao.getRadiosWithId(id).toDomainRadios()
+ }
+
+ override suspend fun insertEntries(entries: List) {
+ entriesDao.insertEntries(entries.toFrameworkEntries())
+ }
+
+ override suspend fun insertRadios(radios: List) {
+ radiosDao.insertRadios(radios.toFrameworkRadios())
+ }
+
+ override suspend fun clearAllData() {
+ entriesDao.deleteEntries()
+ radiosDao.deleteRadios()
+ }
+
+ private fun DomainEntry.toFramework() = FrameworkEntry(this.data, this.comment)
+
+ private fun DomainRadio.toFramework() = FrameworkRadio(
+ this.uuid, this.info, this.isAlive, this.downlink, this.uplink,
+ this.mode, this.isInverted, this.catnum, this.comment
+ )
+
+ private fun FrameworkItem.toDomain() = DomainItem(this.catnum, this.name, this.modes, false)
+
+ private fun FrameworkRadio.toDomain() = DomainRadio(
+ this.uuid, this.info, this.isAlive, this.downlink, this.uplink,
+ this.mode, this.isInverted, this.catnum, this.comment
+ )
+
+ private fun List.toFrameworkEntries() = this.map { entry -> entry.toFramework() }
+
+ private fun List.toFrameworkRadios() = this.map { radio -> radio.toFramework() }
+
+ private fun List.toDomainItems() = this.map { item -> item.toDomain() }
+
+ private fun List.toDomainRadios() = this.map { radio -> radio.toDomain() }
+}
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/local/Look4SatDb.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/StorageDb.kt
similarity index 85%
rename from app/src/main/java/com/rtbishop/look4sat/framework/local/Look4SatDb.kt
rename to app/src/main/java/com/rtbishop/look4sat/framework/data/StorageDb.kt
index 8a6c4db5..a479b2e2 100644
--- a/app/src/main/java/com/rtbishop/look4sat/framework/local/Look4SatDb.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/StorageDb.kt
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package com.rtbishop.look4sat.framework.local
+package com.rtbishop.look4sat.framework.data
import androidx.room.Database
import androidx.room.RoomDatabase
@@ -23,9 +23,9 @@ import com.rtbishop.look4sat.framework.model.SatEntry
import com.rtbishop.look4sat.framework.model.SatRadio
@Database(entities = [SatEntry::class, SatRadio::class], version = 1, exportSchema = true)
-abstract class Look4SatDb : RoomDatabase() {
+abstract class StorageDb : RoomDatabase() {
- abstract fun entriesDao(): SatEntriesDao
+ abstract fun entriesDao(): EntriesDao
- abstract fun radiosDao(): SatRadiosDao
+ abstract fun radiosDao(): RadiosDao
}
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/local/LocalSource.kt b/app/src/main/java/com/rtbishop/look4sat/framework/local/LocalSource.kt
deleted file mode 100644
index d5348298..00000000
--- a/app/src/main/java/com/rtbishop/look4sat/framework/local/LocalSource.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Look4Sat. Amateur radio satellite tracker and pass predictor.
- * Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.rtbishop.look4sat.framework.local
-
-import android.content.ContentResolver
-import android.net.Uri
-import com.rtbishop.look4sat.data.ILocalSource
-import com.rtbishop.look4sat.data.ISettingsHandler
-import com.rtbishop.look4sat.domain.model.SatEntry
-import com.rtbishop.look4sat.domain.model.SatItem
-import com.rtbishop.look4sat.domain.model.SatRadio
-import com.rtbishop.look4sat.domain.predict.Satellite
-import com.rtbishop.look4sat.framework.toDomainItems
-import com.rtbishop.look4sat.framework.toDomainRadios
-import com.rtbishop.look4sat.framework.toFrameworkEntries
-import com.rtbishop.look4sat.framework.toFrameworkRadios
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.withContext
-import java.io.InputStream
-
-class LocalSource(
- private val entriesDao: SatEntriesDao,
- private val radiosDao: SatRadiosDao,
- private val settings: ISettingsHandler,
- private val resolver: ContentResolver,
- private val ioDispatcher: CoroutineDispatcher
-) : ILocalSource {
-
- override fun getEntriesNumber() = entriesDao.getEntriesNumber()
-
- override fun getRadiosNumber() = radiosDao.getRadiosNumber()
-
- override suspend fun getEntriesWithModes(): List {
- val selectedCatnums = getEntriesSelection()
- val entriesWithModes = entriesDao.getEntriesWithModes().toDomainItems()
- entriesWithModes.forEach { entry -> entry.isSelected = entry.catnum in selectedCatnums }
- return entriesWithModes
- }
-
- override suspend fun getSelectedEntries(): List {
- val selectedSatellites = mutableListOf()
- getEntriesSelection().chunked(999).forEach { catnums ->
- val entries = entriesDao.getSelectedEntries(catnums)
- selectedSatellites.addAll(entries.map { entry -> entry.data.createSat() })
- }
- return selectedSatellites
- }
-
- override suspend fun getRadios(catnum: Int): List {
- return radiosDao.getRadios(catnum).toDomainRadios()
- }
-
- @Suppress("BlockingMethodInNonBlockingContext")
- override suspend fun getFileStream(uri: String): InputStream? {
- return withContext(ioDispatcher) { resolver.openInputStream(Uri.parse(uri)) }
- }
-
- override suspend fun insertEntries(entries: List) {
- entriesDao.insertEntries(entries.toFrameworkEntries())
- }
-
- override suspend fun insertRadios(radios: List) {
- radiosDao.insertRadios(radios.toFrameworkRadios())
- }
-
- override suspend fun clearAllData() {
- entriesDao.deleteEntries()
- radiosDao.deleteRadios()
- }
-
- override suspend fun getDataSources(): List {
- return withContext(ioDispatcher) { settings.loadDataSources() }
- }
-
- override suspend fun setDataSources(sources: List) {
- withContext(ioDispatcher) { settings.saveDataSources(sources) }
- }
-
- override suspend fun getEntriesSelection(): List {
- return withContext(ioDispatcher) { settings.loadEntriesSelection() }
- }
-
- override suspend fun setEntriesSelection(catnums: List) {
- withContext(ioDispatcher) { settings.saveEntriesSelection(catnums) }
- }
-}
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/remote/RemoteSource.kt b/app/src/main/java/com/rtbishop/look4sat/framework/remote/RemoteSource.kt
deleted file mode 100644
index c1b4e2a7..00000000
--- a/app/src/main/java/com/rtbishop/look4sat/framework/remote/RemoteSource.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.rtbishop.look4sat.framework.remote
-
-import com.rtbishop.look4sat.data.IRemoteSource
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.withContext
-import java.io.InputStream
-import java.net.URL
-
-class RemoteSource(private val ioDispatcher: CoroutineDispatcher) : IRemoteSource {
-
- @Suppress("BlockingMethodInNonBlockingContext")
- override suspend fun getFileStream(url: String): InputStream? {
- return withContext(ioDispatcher) { URL(url).openStream() }
- }
-}
diff --git a/app/src/main/java/com/rtbishop/look4sat/injection/CoreModule.kt b/app/src/main/java/com/rtbishop/look4sat/injection/CoreModule.kt
index 38b4c438..7937e308 100644
--- a/app/src/main/java/com/rtbishop/look4sat/injection/CoreModule.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/injection/CoreModule.kt
@@ -20,18 +20,18 @@ package com.rtbishop.look4sat.injection
import android.content.Context
import android.content.SharedPreferences
import androidx.room.Room
-import com.rtbishop.look4sat.data.DataRepository
-import com.rtbishop.look4sat.data.ISettingsHandler
-import com.rtbishop.look4sat.domain.DataParser
+import com.rtbishop.look4sat.data.DataParser
+import com.rtbishop.look4sat.data.Repository
import com.rtbishop.look4sat.domain.DataReporter
-import com.rtbishop.look4sat.domain.IDataRepository
import com.rtbishop.look4sat.domain.ILocationHandler
+import com.rtbishop.look4sat.domain.IRepository
+import com.rtbishop.look4sat.domain.ISettings
import com.rtbishop.look4sat.domain.predict.Predictor
import com.rtbishop.look4sat.framework.LocationHandler
import com.rtbishop.look4sat.framework.SettingsHandler
-import com.rtbishop.look4sat.framework.local.LocalSource
-import com.rtbishop.look4sat.framework.local.Look4SatDb
-import com.rtbishop.look4sat.framework.remote.RemoteSource
+import com.rtbishop.look4sat.framework.data.Provider
+import com.rtbishop.look4sat.framework.data.Storage
+import com.rtbishop.look4sat.framework.data.StorageDb
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@@ -49,24 +49,22 @@ object CoreModule {
@Provides
@Singleton
fun provideSatelliteRepo(
- settings: ISettingsHandler,
@ApplicationContext context: Context,
@IoDispatcher ioDispatcher: CoroutineDispatcher,
@DefaultDispatcher defaultDispatcher: CoroutineDispatcher
- ): IDataRepository {
- val db = Room.databaseBuilder(context, Look4SatDb::class.java, "Look4SatDb")
+ ): IRepository {
+ val db = Room.databaseBuilder(context, StorageDb::class.java, "Look4SatDb")
.fallbackToDestructiveMigration().build()
val dataParser = DataParser(defaultDispatcher)
- val resolver = context.contentResolver
- val local = LocalSource(db.entriesDao(), db.radiosDao(), settings, resolver, ioDispatcher)
- val remote = RemoteSource(ioDispatcher)
+ val localSource = Storage(db.entriesDao(), db.radiosDao())
+ val remoteSource = Provider(context.contentResolver, ioDispatcher)
val repositoryScope = CoroutineScope(SupervisorJob())
- return DataRepository(dataParser, local, remote, repositoryScope)
+ return Repository(dataParser, localSource, remoteSource, repositoryScope)
}
@Provides
@Singleton
- fun provideSettingsHandler(sharedPreferences: SharedPreferences): ISettingsHandler {
+ fun provideSettingsHandler(sharedPreferences: SharedPreferences): ISettings {
return SettingsHandler(sharedPreferences)
}
@@ -74,9 +72,9 @@ object CoreModule {
@Singleton
fun provideLocationHandler(
@ApplicationContext context: Context,
- settingsHandler: ISettingsHandler
+ settings: ISettings
): ILocationHandler {
- return LocationHandler(context, settingsHandler)
+ return LocationHandler(context, settings)
}
@Provides
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/Extensions.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/Extensions.kt
deleted file mode 100644
index b1613a5e..00000000
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/Extensions.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Look4Sat. Amateur radio satellite tracker and pass predictor.
- * Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.rtbishop.look4sat.presentation
-
-import android.content.Context
-import android.content.SharedPreferences
-import android.widget.Toast
-import androidx.annotation.IdRes
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleEventObserver
-import androidx.navigation.fragment.findNavController
-
-fun Context.toast(text: String, duration: Int = Toast.LENGTH_SHORT) {
- Toast.makeText(this, text, duration).apply { show() }
-}
-
-fun SharedPreferences.getDouble(key: String, default: Double): Double {
- return Double.fromBits(getLong(key, default.toRawBits()))
-}
-
-fun SharedPreferences.Editor.putDouble(key: String, double: Double) {
- putLong(key, double.toRawBits())
-}
-
-fun Fragment.getNavResult(@IdRes id: Int, key: String, onResult: (result: T) -> Unit) {
- val backStackEntry = findNavController().getBackStackEntry(id)
- val observer = LifecycleEventObserver { _, event ->
- if (event == Lifecycle.Event.ON_RESUME && backStackEntry.savedStateHandle.contains(key)) {
- backStackEntry.savedStateHandle.get(key)?.let(onResult)
- backStackEntry.savedStateHandle.remove(key)
- }
- }
- backStackEntry.lifecycle.addObserver(observer)
- viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
- if (event == Lifecycle.Event.ON_DESTROY) backStackEntry.lifecycle.removeObserver(observer)
- })
-}
-
-fun Fragment.setNavResult(key: String, value: T) {
- findNavController().previousBackStackEntry?.savedStateHandle?.set(key, value)
-}
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt
index 80066242..42d005d6 100644
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt
@@ -20,23 +20,42 @@ package com.rtbishop.look4sat.presentation
import android.annotation.SuppressLint
import android.content.pm.ActivityInfo
import android.os.Bundle
-import androidx.activity.viewModels
+import androidx.annotation.IdRes
import androidx.appcompat.app.AppCompatActivity
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.navigation.fragment.findNavController
import com.rtbishop.look4sat.databinding.ActivityMainBinding
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
- private val mainViewModel: MainViewModel by viewModels()
-
@SuppressLint("SourceLockedOrientationActivity")
override fun onCreate(savedInstanceState: Bundle?) {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
installSplashScreen()
super.onCreate(savedInstanceState)
setContentView(ActivityMainBinding.inflate(layoutInflater).root)
- mainViewModel.calculatePasses()
}
}
+
+fun Fragment.getNavResult(@IdRes id: Int, key: String, onResult: (result: T) -> Unit) {
+ val backStackEntry = findNavController().getBackStackEntry(id)
+ val observer = LifecycleEventObserver { _, event ->
+ if (event == Lifecycle.Event.ON_RESUME && backStackEntry.savedStateHandle.contains(key)) {
+ backStackEntry.savedStateHandle.get(key)?.let(onResult)
+ backStackEntry.savedStateHandle.remove(key)
+ }
+ }
+ backStackEntry.lifecycle.addObserver(observer)
+ viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
+ if (event == Lifecycle.Event.ON_DESTROY) backStackEntry.lifecycle.removeObserver(observer)
+ })
+}
+
+fun Fragment.setNavResult(key: String, value: T) {
+ findNavController().previousBackStackEntry?.savedStateHandle?.set(key, value)
+}
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/Look4SatApplication.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/MainApplication.kt
similarity index 95%
rename from app/src/main/java/com/rtbishop/look4sat/presentation/Look4SatApplication.kt
rename to app/src/main/java/com/rtbishop/look4sat/presentation/MainApplication.kt
index ae51dce4..4fe1d8e4 100644
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/Look4SatApplication.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/presentation/MainApplication.kt
@@ -21,4 +21,4 @@ import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
-class Look4SatApplication : Application()
+class MainApplication : Application()
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/MainViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/MainViewModel.kt
deleted file mode 100644
index 59d96fe6..00000000
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/MainViewModel.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.rtbishop.look4sat.presentation
-
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.viewModelScope
-import com.rtbishop.look4sat.data.ISettingsHandler
-import com.rtbishop.look4sat.domain.IDataRepository
-import com.rtbishop.look4sat.domain.predict.Predictor
-import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.launch
-import javax.inject.Inject
-
-@HiltViewModel
-class MainViewModel @Inject constructor(
- private val predictor: Predictor,
- private val preferences: ISettingsHandler,
- private val dataRepository: IDataRepository
-) : ViewModel() {
-
- fun calculatePasses(
- hoursAhead: Int = preferences.getHoursAhead(),
- minElevation: Double = preferences.getMinElevation(),
- timeRef: Long = System.currentTimeMillis()
- ) {
- viewModelScope.launch {
- val satellites = dataRepository.getSelectedEntries()
- val stationPos = preferences.loadStationPosition()
- predictor.forceCalculation(satellites, stationPos, timeRef, hoursAhead, minElevation)
- }
- }
-}
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesFragment.kt
index fc543e83..c465c737 100644
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesFragment.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesFragment.kt
@@ -39,8 +39,8 @@ import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class EntriesFragment : Fragment(R.layout.fragment_entries) {
- private lateinit var binding: FragmentEntriesBinding
private val viewModel: EntriesViewModel by viewModels()
+ private lateinit var binding: FragmentEntriesBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt
index 7285b5f8..fe3ca302 100644
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt
@@ -18,8 +18,8 @@
package com.rtbishop.look4sat.presentation.entriesScreen
import androidx.lifecycle.*
-import com.rtbishop.look4sat.data.ISettingsHandler
-import com.rtbishop.look4sat.domain.IDataRepository
+import com.rtbishop.look4sat.domain.IRepository
+import com.rtbishop.look4sat.domain.ISettings
import com.rtbishop.look4sat.domain.model.DataState
import com.rtbishop.look4sat.domain.model.SatItem
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -28,13 +28,13 @@ import javax.inject.Inject
@HiltViewModel
class EntriesViewModel @Inject constructor(
- private val preferences: ISettingsHandler,
- private val repository: IDataRepository
+ private val repository: IRepository,
+ private val settings: ISettings
) : ViewModel(), EntriesAdapter.EntriesClickListener {
- private val transModes = MutableLiveData(preferences.loadModesSelection())
+ private val transModes = MutableLiveData(settings.loadModesSelection())
private val currentQuery = MutableLiveData(String())
- private val itemsFromRepo = liveData { emit(repository.getEntriesWithModes()) } as MutableLiveData
+ private val itemsFromRepo = liveData { emit(loadEntriesWithSelection()) } as MutableLiveData
private val itemsWithModes = transModes.switchMap { modes ->
itemsFromRepo.map { items -> filterByModes(items, modes) }
}
@@ -51,7 +51,7 @@ class EntriesViewModel @Inject constructor(
fun saveSelectedModes(modes: List) {
transModes.value = modes
- preferences.saveModesSelection(modes)
+ settings.saveModesSelection(modes)
}
fun setQuery(query: String) {
@@ -74,6 +74,11 @@ class EntriesViewModel @Inject constructor(
}
}
+ private suspend fun loadEntriesWithSelection(): List {
+ val selectedIds = settings.loadEntriesSelection()
+ return repository.getEntriesWithModes().onEach { it.isSelected = it.catnum in selectedIds }
+ }
+
private fun filterByModes(items: List, modes: List): List {
if (modes.isEmpty()) return items
return items.filter { item -> item.modes.any { mode -> mode in modes } }
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/ModesDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/ModesDialog.kt
index 436b3440..7f234fdc 100644
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/ModesDialog.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/ModesDialog.kt
@@ -9,8 +9,8 @@ import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.SimpleItemAnimator
import com.rtbishop.look4sat.R
-import com.rtbishop.look4sat.data.ISettingsHandler
import com.rtbishop.look4sat.databinding.DialogModesBinding
+import com.rtbishop.look4sat.domain.ISettings
import com.rtbishop.look4sat.presentation.setNavResult
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@@ -19,7 +19,7 @@ import javax.inject.Inject
class ModesDialog : AppCompatDialogFragment(), ModesAdapter.ModesClickListener {
@Inject
- lateinit var preferences: ISettingsHandler
+ lateinit var preferences: ISettings
private lateinit var binding: DialogModesBinding
private val allModes = listOf(
"AFSK", "AFSK S-Net", "AFSK SALSAT", "AHRPT", "AM", "APT", "BPSK", "BPSK PMT-A3",
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapFragment.kt
index e1b3e9ca..33c6b47c 100644
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapFragment.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapFragment.kt
@@ -17,7 +17,7 @@
*/
package com.rtbishop.look4sat.presentation.mapScreen
-import android.content.SharedPreferences
+import android.content.Context
import android.graphics.Color
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
@@ -43,17 +43,12 @@ import org.osmdroid.views.overlay.FolderOverlay
import org.osmdroid.views.overlay.Marker
import org.osmdroid.views.overlay.Polygon
import org.osmdroid.views.overlay.Polyline
-import javax.inject.Inject
@AndroidEntryPoint
class MapFragment : Fragment(R.layout.fragment_map) {
- @Inject
- lateinit var sharedPreferences: SharedPreferences
- private lateinit var binding: FragmentMapBinding
-
- private val args: MapFragmentArgs by navArgs()
private val viewModel: MapViewModel by viewModels()
+ private val navArgs: MapFragmentArgs by navArgs()
private val minLat = MapView.getTileSystem().minLatitude
private val maxLat = MapView.getTileSystem().maxLatitude
private val trackPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
@@ -67,6 +62,7 @@ class MapFragment : Fragment(R.layout.fragment_map) {
style = Paint.Style.FILL_AND_STROKE
color = Color.parseColor("#26FFE082")
}
+ private lateinit var binding: FragmentMapBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -76,7 +72,9 @@ class MapFragment : Fragment(R.layout.fragment_map) {
}
private fun setupComponents() {
- Configuration.getInstance().load(requireContext(), sharedPreferences)
+ val context = requireContext()
+ val preferences = context.getSharedPreferences("default", Context.MODE_PRIVATE)
+ Configuration.getInstance().load(context, preferences)
binding.run {
mapView.apply {
setMultiTouchControls(true)
@@ -99,15 +97,15 @@ class MapFragment : Fragment(R.layout.fragment_map) {
}
private fun setupObservers() {
- viewModel.selectDefaultSatellite(args.catNum)
- viewModel.stationPosLiveData.observe(viewLifecycleOwner) { renderStationPos(it) }
- viewModel.satPositions.observe(viewLifecycleOwner) { renderSatPositions(it) }
- viewModel.satTrack.observe(viewLifecycleOwner) { renderSatTrack(it) }
- viewModel.satFootprint.observe(viewLifecycleOwner) { renderSatFootprint(it) }
- viewModel.mapData.observe(viewLifecycleOwner) { renderSatData(it) }
+ viewModel.selectDefaultSatellite(navArgs.catNum)
+ viewModel.stationPos.observe(viewLifecycleOwner) { handleStationPos(it) }
+ viewModel.positions.observe(viewLifecycleOwner) { handlePositions(it) }
+ viewModel.track.observe(viewLifecycleOwner) { handleTrack(it) }
+ viewModel.footprint.observe(viewLifecycleOwner) { handleFootprint(it) }
+ viewModel.mapData.observe(viewLifecycleOwner) { handleMapData(it) }
}
- private fun renderStationPos(stationPos: GeoPos) {
+ private fun handleStationPos(stationPos: GeoPos) {
binding.apply {
Marker(mapView).apply {
setInfoWindow(null)
@@ -120,7 +118,7 @@ class MapFragment : Fragment(R.layout.fragment_map) {
}
}
- private fun renderSatPositions(posMap: Map) {
+ private fun handlePositions(posMap: Map) {
binding.apply {
val markers = FolderOverlay()
posMap.entries.forEach {
@@ -149,7 +147,7 @@ class MapFragment : Fragment(R.layout.fragment_map) {
}
}
- private fun renderSatTrack(satTrack: List>) {
+ private fun handleTrack(satTrack: List>) {
val trackOverlay = FolderOverlay()
satTrack.forEach { track ->
val trackPoints = track.map { GeoPoint(it.latitude, it.longitude) }
@@ -166,7 +164,7 @@ class MapFragment : Fragment(R.layout.fragment_map) {
binding.mapView.overlays[1] = trackOverlay
}
- private fun renderSatFootprint(satFootprint: List) {
+ private fun handleFootprint(satFootprint: List) {
val footprintPoints = satFootprint.map { GeoPoint(it.latitude, it.longitude) }
val footprintOverlay = Polygon().apply {
fillPaint.set(footprintPaint)
@@ -180,7 +178,7 @@ class MapFragment : Fragment(R.layout.fragment_map) {
binding.mapView.overlays[2] = footprintOverlay
}
- private fun renderSatData(mapData: MapData) {
+ private fun handleMapData(mapData: MapData) {
binding.apply {
mapDataName.text =
String.format(getString(R.string.pat_osm_idName), mapData.catNum, mapData.name)
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt
index 2804b18b..e5b282ed 100644
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt
@@ -18,8 +18,8 @@
package com.rtbishop.look4sat.presentation.mapScreen
import androidx.lifecycle.*
-import com.rtbishop.look4sat.data.ISettingsHandler
-import com.rtbishop.look4sat.domain.IDataRepository
+import com.rtbishop.look4sat.domain.IRepository
+import com.rtbishop.look4sat.domain.ISettings
import com.rtbishop.look4sat.domain.QthConverter
import com.rtbishop.look4sat.domain.predict.GeoPos
import com.rtbishop.look4sat.domain.predict.Predictor
@@ -33,52 +33,54 @@ import kotlin.math.min
@HiltViewModel
class MapViewModel @Inject constructor(
- private val dataRepository: IDataRepository,
private val predictor: Predictor,
- preferences: ISettingsHandler,
+ private val repository: IRepository,
+ private val settings: ISettings,
) : ViewModel() {
- private val stationPos = preferences.loadStationPosition()
+ private val stationPosition = settings.loadStationPosition()
+ private var allSatellites = listOf()
private var dataUpdateJob: Job? = null
- private var allSatList = listOf()
- private lateinit var selectedSat: Satellite
+ private var dataUpdateRate = 2000L
+ private lateinit var selectedSatellite: Satellite
- val stationPosLiveData = liveData {
- val osmLat = clipLat(stationPos.latitude)
- val osmLon = clipLon(stationPos.longitude)
+ val stationPos = liveData {
+ val osmLat = clipLat(stationPosition.latitude)
+ val osmLon = clipLon(stationPosition.longitude)
emit(GeoPos(osmLat, osmLon))
}
- private val _satTrack = MutableLiveData>>()
- val satTrack: LiveData>> = _satTrack
+ private val _track = MutableLiveData>>()
+ val track: LiveData>> = _track
- private val _satFootprint = MutableLiveData>()
- val satFootprint: LiveData> = _satFootprint
+ private val _footprint = MutableLiveData>()
+ val footprint: LiveData> = _footprint
- private val _satData = MutableLiveData()
- val mapData: LiveData = this._satData
+ private val _mapData = MutableLiveData()
+ val mapData: LiveData = this._mapData
- private val _satPositions = MutableLiveData