kopia lustrzana https://github.com/rt-bishop/Look4Sat
Moved and renamed various classes to simplify structure
rodzic
c91c58ac69
commit
fdb5752408
|
@ -21,7 +21,7 @@ import android.content.SharedPreferences
|
|||
import android.hardware.GeomagneticField
|
||||
import android.location.LocationManager
|
||||
import androidx.core.content.edit
|
||||
import com.rtbishop.look4sat.data.PreferenceSource
|
||||
import com.rtbishop.look4sat.data.PreferencesSource
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.QthConverter
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
|
||||
import com.rtbishop.look4sat.utility.round
|
||||
|
@ -31,7 +31,7 @@ class PreferencesProvider @Inject constructor(
|
|||
private val qthConverter: QthConverter,
|
||||
private val locationManager: LocationManager,
|
||||
private val preferences: SharedPreferences
|
||||
) : PreferenceSource {
|
||||
) : PreferencesSource {
|
||||
|
||||
companion object {
|
||||
const val keyModes = "satModes"
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package com.rtbishop.look4sat.framework.api
|
||||
|
||||
import com.rtbishop.look4sat.data.RemoteDataSource
|
||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import java.io.InputStream
|
||||
|
||||
class NetworkDataSource(private val api: SatelliteService) : RemoteDataSource {
|
||||
|
||||
override suspend fun fetchDataStream(url: String): InputStream? {
|
||||
return api.fetchFileByUrl(url).body()?.byteStream()
|
||||
}
|
||||
|
||||
override suspend fun fetchTransmitters(): List<SatTrans> {
|
||||
return api.fetchTransmitters().map { trans ->
|
||||
SatTrans(
|
||||
trans.uuid, trans.info, trans.isAlive, trans.downlink,
|
||||
trans.uplink, trans.mode, trans.isInverted, trans.catNum
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.rtbishop.look4sat.framework.api
|
||||
|
||||
import com.rtbishop.look4sat.data.SatDataRemoteSource
|
||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import com.rtbishop.look4sat.utility.DataMapper
|
||||
import java.io.InputStream
|
||||
|
||||
class SatDataRemote(private val api: SatDataService) : SatDataRemoteSource {
|
||||
|
||||
override suspend fun fetchDataStream(url: String): InputStream? {
|
||||
return api.fetchFileByUrl(url).body()?.byteStream()
|
||||
}
|
||||
|
||||
override suspend fun fetchTransmitters(): List<SatTrans> {
|
||||
return DataMapper.satTransListToDomainTransList(api.fetchTransmitters())
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ import retrofit2.http.GET
|
|||
import retrofit2.http.Streaming
|
||||
import retrofit2.http.Url
|
||||
|
||||
interface SatelliteService {
|
||||
interface SatDataService {
|
||||
|
||||
@Streaming
|
||||
@GET
|
|
@ -25,7 +25,7 @@ import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface SatelliteDao {
|
||||
interface SatDataDao {
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT catNum, name, isSelected FROM entries ORDER BY name ASC")
|
|
@ -25,7 +25,7 @@ import com.rtbishop.look4sat.framework.model.SatTrans
|
|||
|
||||
@Database(entities = [SatEntry::class, SatTrans::class], version = 1, exportSchema = false)
|
||||
@TypeConverters(RoomConverters::class)
|
||||
abstract class SatelliteDb : RoomDatabase() {
|
||||
abstract class SatDataDb : RoomDatabase() {
|
||||
|
||||
abstract fun satelliteDao(): SatelliteDao
|
||||
abstract fun satelliteDao(): SatDataDao
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package com.rtbishop.look4sat.framework.db
|
||||
|
||||
import com.rtbishop.look4sat.data.LocalDataSource
|
||||
import com.rtbishop.look4sat.data.SatDataLocalSource
|
||||
import com.rtbishop.look4sat.domain.model.SatEntry
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
|
@ -9,33 +9,33 @@ import com.rtbishop.look4sat.utility.DataMapper
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class RoomDataSource(private val satelliteDao: SatelliteDao) : LocalDataSource {
|
||||
class SatDataLocal(private val satDataDao: SatDataDao) : SatDataLocalSource {
|
||||
|
||||
override fun getSatItems(): Flow<List<SatItem>> {
|
||||
return satelliteDao.getSatItems()
|
||||
return satDataDao.getSatItems()
|
||||
.map { satItems -> DataMapper.satItemsToDomainItems(satItems) }
|
||||
}
|
||||
|
||||
override suspend fun getSelectedSatellites(): List<Satellite> {
|
||||
return satelliteDao.getSelectedSatellites()
|
||||
return satDataDao.getSelectedSatellites()
|
||||
}
|
||||
|
||||
override suspend fun updateEntries(entries: List<SatEntry>) {
|
||||
val satEntries = entries.map { entry -> DataMapper.domainEntryToSatEntry(entry) }
|
||||
satelliteDao.updateEntries(satEntries)
|
||||
satDataDao.updateEntries(satEntries)
|
||||
}
|
||||
|
||||
override suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
|
||||
satelliteDao.updateEntriesSelection(catNums, isSelected)
|
||||
satDataDao.updateEntriesSelection(catNums, isSelected)
|
||||
}
|
||||
|
||||
override fun getSatTransmitters(catNum: Int): Flow<List<SatTrans>> {
|
||||
return satelliteDao.getSatTransmitters(catNum)
|
||||
return satDataDao.getSatTransmitters(catNum)
|
||||
.map { satTransList -> DataMapper.satTransListToDomainTransList(satTransList) }
|
||||
}
|
||||
|
||||
override suspend fun updateTransmitters(satelliteTrans: List<SatTrans>) {
|
||||
val satTransList = DataMapper.domainTransListToSatTransList(satelliteTrans)
|
||||
satelliteDao.updateTransmitters(satTransList)
|
||||
satDataDao.updateTransmitters(satTransList)
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.di
|
||||
package com.rtbishop.look4sat.injection
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
|
@ -23,7 +23,6 @@ import android.content.SharedPreferences
|
|||
import android.hardware.SensorManager
|
||||
import android.location.LocationManager
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.QthConverter
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
@ -34,11 +33,6 @@ import dagger.hilt.components.SingletonComponent
|
|||
@InstallIn(SingletonComponent::class)
|
||||
object ApplicationModule {
|
||||
|
||||
@Provides
|
||||
fun provideQthConverter(): QthConverter {
|
||||
return QthConverter()
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideContentResolver(@ApplicationContext context: Context): ContentResolver {
|
||||
return context.contentResolver
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.di
|
||||
package com.rtbishop.look4sat.injection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.di
|
||||
package com.rtbishop.look4sat.injection
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
|
@ -24,12 +24,12 @@ import androidx.room.Room
|
|||
import com.rtbishop.look4sat.data.*
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.QthConverter
|
||||
import com.rtbishop.look4sat.framework.PreferencesProvider
|
||||
import com.rtbishop.look4sat.framework.api.NetworkDataSource
|
||||
import com.rtbishop.look4sat.framework.api.SatelliteService
|
||||
import com.rtbishop.look4sat.framework.api.SatDataRemote
|
||||
import com.rtbishop.look4sat.framework.api.SatDataService
|
||||
import com.rtbishop.look4sat.framework.db.RoomConverters
|
||||
import com.rtbishop.look4sat.framework.db.RoomDataSource
|
||||
import com.rtbishop.look4sat.framework.db.SatelliteDao
|
||||
import com.rtbishop.look4sat.framework.db.SatelliteDb
|
||||
import com.rtbishop.look4sat.framework.db.SatDataLocal
|
||||
import com.rtbishop.look4sat.framework.db.SatDataDao
|
||||
import com.rtbishop.look4sat.framework.db.SatDataDb
|
||||
import com.squareup.moshi.Moshi
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
@ -43,7 +43,12 @@ import javax.inject.Singleton
|
|||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object DataSourceModule {
|
||||
object SatDataModule {
|
||||
|
||||
@Provides
|
||||
fun provideQthConverter(): QthConverter {
|
||||
return QthConverter()
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideMoshi(): Moshi {
|
||||
|
@ -56,56 +61,57 @@ object DataSourceModule {
|
|||
qthConverter: QthConverter,
|
||||
locationManager: LocationManager,
|
||||
preferences: SharedPreferences
|
||||
): PreferenceSource {
|
||||
): PreferencesSource {
|
||||
return PreferencesProvider(qthConverter, locationManager, preferences)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providePassesRepo(
|
||||
preferenceSource: PreferenceSource,
|
||||
preferencesSource: PreferencesSource,
|
||||
@DefaultDispatcher defaultDispatcher: CoroutineDispatcher
|
||||
): PassesRepo {
|
||||
return PassesRepo(preferenceSource, defaultDispatcher)
|
||||
): SatPassRepository {
|
||||
return SatPassRepository(preferencesSource, defaultDispatcher)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSatelliteRepo(
|
||||
localSource: LocalDataSource,
|
||||
remoteSource: RemoteDataSource,
|
||||
preferencesSource: PreferencesSource,
|
||||
satLocalSource: SatDataLocalSource,
|
||||
satRemoteSource: SatDataRemoteSource,
|
||||
@IoDispatcher ioDispatcher: CoroutineDispatcher
|
||||
): SatelliteRepo {
|
||||
return SatelliteRepo(localSource, remoteSource, ioDispatcher)
|
||||
): SatDataRepository {
|
||||
return SatDataRepository(preferencesSource, satLocalSource, satRemoteSource, ioDispatcher)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideLocalDataSource(satelliteDao: SatelliteDao): LocalDataSource {
|
||||
return RoomDataSource(satelliteDao)
|
||||
fun provideLocalDataSource(satDataDao: SatDataDao): SatDataLocalSource {
|
||||
return SatDataLocal(satDataDao)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideSatDataDao(db: SatelliteDb): SatelliteDao {
|
||||
fun provideSatDataDao(db: SatDataDb): SatDataDao {
|
||||
return db.satelliteDao()
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideSatelliteDb(@ApplicationContext context: Context, moshi: Moshi): SatelliteDb {
|
||||
fun provideSatelliteDb(@ApplicationContext context: Context, moshi: Moshi): SatDataDb {
|
||||
RoomConverters.initialize(moshi)
|
||||
return Room.databaseBuilder(context, SatelliteDb::class.java, "SatelliteDb").build()
|
||||
return Room.databaseBuilder(context, SatDataDb::class.java, "SatelliteDb").build()
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideRemoteDataSource(satelliteService: SatelliteService): RemoteDataSource {
|
||||
return NetworkDataSource(satelliteService)
|
||||
fun provideRemoteDataSource(satDataService: SatDataService): SatDataRemoteSource {
|
||||
return SatDataRemote(satDataService)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideSatDataService(): SatelliteService {
|
||||
fun provideSatDataService(): SatDataService {
|
||||
return Retrofit.Builder()
|
||||
.baseUrl("https://db.satnogs.org/api/")
|
||||
.addConverterFactory(MoshiConverterFactory.create())
|
||||
.build()
|
||||
.create(SatelliteService::class.java)
|
||||
.create(SatDataService::class.java)
|
||||
}
|
||||
}
|
|
@ -24,8 +24,8 @@ import androidx.appcompat.app.AppCompatActivity
|
|||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.PreferencesSource
|
||||
import com.rtbishop.look4sat.databinding.ActivityMainBinding
|
||||
import com.rtbishop.look4sat.framework.PreferencesProvider
|
||||
import com.rtbishop.look4sat.utility.navigateSafe
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
@ -34,7 +34,7 @@ import javax.inject.Inject
|
|||
class Look4SatActivity : AppCompatActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var preferenceSource: PreferencesProvider
|
||||
lateinit var preferenceSource: PreferencesSource
|
||||
|
||||
@SuppressLint("SourceLockedOrientationActivity")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.infoScreen
|
||||
package com.rtbishop.look4sat.presentation.appInfoScreen
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
|
@ -27,7 +27,7 @@ import com.rtbishop.look4sat.BuildConfig
|
|||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.databinding.FragmentInfoBinding
|
||||
|
||||
class InfoFragment : Fragment(R.layout.fragment_info) {
|
||||
class AppInfoFragment : Fragment(R.layout.fragment_info) {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.prefsScreen
|
||||
package com.rtbishop.look4sat.presentation.appSettingsScreen
|
||||
|
||||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
|
@ -30,16 +30,16 @@ import androidx.preference.Preference
|
|||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.PreferenceSource
|
||||
import com.rtbishop.look4sat.data.PreferencesSource
|
||||
import com.rtbishop.look4sat.framework.PreferencesProvider
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class PrefsFragment : PreferenceFragmentCompat() {
|
||||
class AppSettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
@Inject
|
||||
lateinit var preferenceSource: PreferenceSource
|
||||
lateinit var preferencesSource: PreferencesSource
|
||||
|
||||
private val requestPermissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
|
||||
|
@ -96,7 +96,7 @@ class PrefsFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
|
||||
private fun updatePositionFromQth(qthString: String): Boolean {
|
||||
return if (preferenceSource.updatePositionFromQTH(qthString)) {
|
||||
return if (preferencesSource.updatePositionFromQTH(qthString)) {
|
||||
showSnack(getString(R.string.pref_pos_success))
|
||||
true
|
||||
} else {
|
||||
|
@ -109,7 +109,7 @@ class PrefsFragment : PreferenceFragmentCompat() {
|
|||
val locPermString = Manifest.permission.ACCESS_FINE_LOCATION
|
||||
val locPermResult = ContextCompat.checkSelfPermission(requireContext(), locPermString)
|
||||
if (locPermResult == PackageManager.PERMISSION_GRANTED) {
|
||||
if (preferenceSource.updatePositionFromGPS()) {
|
||||
if (preferencesSource.updatePositionFromGPS()) {
|
||||
showSnack(getString(R.string.pref_pos_success))
|
||||
} else showSnack(getString(R.string.pref_pos_gps_null))
|
||||
} else requestPermissionLauncher.launch(locPermString)
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.splashDialog
|
||||
package com.rtbishop.look4sat.presentation.appSplashDialog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
|
@ -26,7 +26,7 @@ import androidx.appcompat.app.AppCompatDialogFragment
|
|||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.databinding.DialogSplashBinding
|
||||
|
||||
class SplashDialog : AppCompatDialogFragment() {
|
||||
class AppSplashDialog : AppCompatDialogFragment() {
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, group: ViewGroup?, state: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.dialog_splash, group, false)
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.entriesScreen
|
||||
package com.rtbishop.look4sat.presentation.satItemScreen
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
|
@ -25,7 +25,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.rtbishop.look4sat.databinding.SatItemBinding
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
|
||||
class EntriesAdapter : RecyclerView.Adapter<EntriesAdapter.SatItemHolder>() {
|
||||
class SatItemAdapter : RecyclerView.Adapter<SatItemAdapter.SatItemHolder>() {
|
||||
|
||||
private val diffCallback = object : DiffUtil.ItemCallback<SatItem>() {
|
||||
override fun areItemsTheSame(oldItem: SatItem, newItem: SatItem): Boolean {
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.entriesScreen
|
||||
package com.rtbishop.look4sat.presentation.satItemScreen
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
|
@ -33,9 +33,9 @@ import com.rtbishop.look4sat.utility.RecyclerDivider
|
|||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class EntriesFragment : Fragment(R.layout.fragment_entries) {
|
||||
class SatItemFragment : Fragment(R.layout.fragment_entries) {
|
||||
|
||||
private val viewModel: EntriesViewModel by viewModels()
|
||||
private val viewModel: SatItemViewModel by viewModels()
|
||||
private val contentContract = ActivityResultContracts.GetContent()
|
||||
private val filePicker = registerForActivityResult(contentContract) { uri ->
|
||||
uri?.let { viewModel.updateEntriesFromFile(uri) }
|
||||
|
@ -47,7 +47,7 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) {
|
|||
}
|
||||
|
||||
private fun setupComponents(view: View) {
|
||||
val entriesAdapter = EntriesAdapter().apply {
|
||||
val entriesAdapter = SatItemAdapter().apply {
|
||||
setEntriesClickListener(viewModel)
|
||||
}
|
||||
val binding = FragmentEntriesBinding.bind(view).apply {
|
||||
|
@ -72,11 +72,11 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) {
|
|||
private fun handleSatData(
|
||||
result: Result<List<SatItem>>,
|
||||
binding: FragmentEntriesBinding,
|
||||
entriesAdapter: EntriesAdapter
|
||||
satItemAdapter: SatItemAdapter
|
||||
) {
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
entriesAdapter.submitList(result.data)
|
||||
satItemAdapter.submitList(result.data)
|
||||
binding.entriesProgress.visibility = View.INVISIBLE
|
||||
binding.entriesRecycler.visibility = View.VISIBLE
|
||||
binding.entriesRecycler.scrollToPosition(0)
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.entriesScreen
|
||||
package com.rtbishop.look4sat.presentation.satItemScreen
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
|
@ -25,9 +25,8 @@ import androidx.appcompat.app.AlertDialog
|
|||
import androidx.lifecycle.*
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.SatelliteRepo
|
||||
import com.rtbishop.look4sat.data.SatDataRepository
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
import com.rtbishop.look4sat.framework.PreferencesProvider
|
||||
import com.rtbishop.look4sat.framework.model.Result
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.collect
|
||||
|
@ -36,16 +35,15 @@ import java.util.*
|
|||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class EntriesViewModel @Inject constructor(
|
||||
private val preferenceSource: PreferencesProvider,
|
||||
class SatItemViewModel @Inject constructor(
|
||||
private val resolver: ContentResolver,
|
||||
private val satelliteRepo: SatelliteRepo,
|
||||
) : ViewModel(), EntriesAdapter.EntriesClickListener, SearchView.OnQueryTextListener {
|
||||
private val satDataRepository: SatDataRepository,
|
||||
) : ViewModel(), SatItemAdapter.EntriesClickListener, SearchView.OnQueryTextListener {
|
||||
|
||||
private val transModes = MutableLiveData(preferenceSource.loadModesSelection())
|
||||
private val transModes = MutableLiveData(satDataRepository.loadModesSelection())
|
||||
private val currentQuery = MutableLiveData(String())
|
||||
private val itemsWithModes = transModes.switchMap { modes ->
|
||||
liveData { satelliteRepo.getSatItems().collect { emit(filterByModes(it, modes)) } }
|
||||
liveData { satDataRepository.getSatItems().collect { emit(filterByModes(it, modes)) } }
|
||||
}
|
||||
private val itemsWithQuery = currentQuery.switchMap { query ->
|
||||
itemsWithModes.map { items -> Result.Success(filterByQuery(items, query)) }
|
||||
|
@ -61,7 +59,7 @@ class EntriesViewModel @Inject constructor(
|
|||
_satData.value = Result.InProgress
|
||||
runCatching {
|
||||
resolver.openInputStream(uri)?.use { stream ->
|
||||
satelliteRepo.updateEntriesFromFile(stream)
|
||||
satDataRepository.updateEntriesFromFile(stream)
|
||||
}
|
||||
}.onFailure { _satData.value = Result.Error(it) }
|
||||
}
|
||||
|
@ -71,8 +69,8 @@ class EntriesViewModel @Inject constructor(
|
|||
viewModelScope.launch {
|
||||
_satData.value = Result.InProgress
|
||||
runCatching {
|
||||
if (sources == null) satelliteRepo.updateEntriesFromWeb()
|
||||
else satelliteRepo.updateEntriesFromWeb(sources)
|
||||
if (sources == null) satDataRepository.updateEntriesFromWeb()
|
||||
else satDataRepository.updateEntriesFromWeb(sources)
|
||||
}.onFailure { _satData.value = Result.Error(it) }
|
||||
}
|
||||
}
|
||||
|
@ -86,15 +84,9 @@ class EntriesViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun createModesDialog(context: Context): AlertDialog {
|
||||
val modes = arrayOf(
|
||||
"AFSK", "AFSK S-Net", "AFSK SALSAT", "AHRPT", "AM", "APT", "BPSK", "BPSK PMT-A3",
|
||||
"CERTO", "CW", "DQPSK", "DSTAR", "DUV", "FFSK", "FM", "FMN", "FSK", "FSK AX.100 Mode 5",
|
||||
"FSK AX.100 Mode 6", "FSK AX.25 G3RUH", "GFSK", "GFSK Rktr", "GMSK", "HRPT", "LoRa",
|
||||
"LRPT", "LSB", "MFSK", "MSK", "MSK AX.100 Mode 5", "MSK AX.100 Mode 6", "OFDM", "OQPSK",
|
||||
"PSK", "PSK31", "PSK63", "QPSK", "QPSK31", "QPSK63", "SSTV", "USB", "WSJT"
|
||||
)
|
||||
val modes = satDataRepository.getAllModes()
|
||||
val savedModes = BooleanArray(modes.size)
|
||||
val selectedModes = preferenceSource.loadModesSelection().toMutableList()
|
||||
val selectedModes = satDataRepository.loadModesSelection().toMutableList()
|
||||
selectedModes.forEach { savedModes[modes.indexOf(it)] = true }
|
||||
val dialogBuilder = MaterialAlertDialogBuilder(context).apply {
|
||||
setTitle(context.getString(R.string.modes_title))
|
||||
|
@ -106,7 +98,7 @@ class EntriesViewModel @Inject constructor(
|
|||
}
|
||||
setPositiveButton(context.getString(android.R.string.ok)) { _, _ ->
|
||||
transModes.value = selectedModes
|
||||
preferenceSource.saveModesSelection(selectedModes)
|
||||
satDataRepository.saveModesSelection(selectedModes)
|
||||
}
|
||||
setNeutralButton(context.getString(android.R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
|
@ -125,7 +117,7 @@ class EntriesViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun updateSelection(catNums: List<Int>, isSelected: Boolean) {
|
||||
viewModelScope.launch { satelliteRepo.updateEntriesSelection(catNums, isSelected) }
|
||||
viewModelScope.launch { satDataRepository.updateEntriesSelection(catNums, isSelected) }
|
||||
}
|
||||
|
||||
private fun filterByModes(items: List<SatItem>, modes: List<String>): List<SatItem> {
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.mapScreen
|
||||
package com.rtbishop.look4sat.presentation.satMapScreen
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Color
|
||||
|
@ -44,12 +44,12 @@ import java.util.*
|
|||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MapFragment : Fragment(R.layout.fragment_map) {
|
||||
class SatMapFragment : Fragment(R.layout.fragment_map) {
|
||||
|
||||
@Inject
|
||||
lateinit var sharedPreferences: SharedPreferences
|
||||
|
||||
private val viewModel: MapViewModel by viewModels()
|
||||
private val viewModelSat: SatMapViewModel by viewModels()
|
||||
private val minLat = MapView.getTileSystem().minLatitude
|
||||
private val maxLat = MapView.getTileSystem().maxLatitude
|
||||
private val trackPaint = Paint().apply {
|
||||
|
@ -86,17 +86,17 @@ class MapFragment : Fragment(R.layout.fragment_map) {
|
|||
overlays.addAll(Array(4) { FolderOverlay() })
|
||||
}
|
||||
}
|
||||
binding.fabPrev.setOnClickListener { viewModel.scrollSelection(true) }
|
||||
binding.fabNext.setOnClickListener { viewModel.scrollSelection(false) }
|
||||
binding.fabPrev.setOnClickListener { viewModelSat.scrollSelection(true) }
|
||||
binding.fabNext.setOnClickListener { viewModelSat.scrollSelection(false) }
|
||||
setupObservers(binding)
|
||||
}
|
||||
|
||||
private fun setupObservers(binding: FragmentMapBinding) {
|
||||
viewModel.stationPos.observe(viewLifecycleOwner, { renderStationPos(it, binding) })
|
||||
viewModel.allSatPositions.observe(viewLifecycleOwner, { renderSatPositions(it, binding) })
|
||||
viewModel.satTrack.observe(viewLifecycleOwner, { renderSatTrack(it, binding) })
|
||||
viewModel.satFootprint.observe(viewLifecycleOwner, { renderSatFootprint(it, binding) })
|
||||
viewModel.satData.observe(viewLifecycleOwner, { renderSatData(it, binding) })
|
||||
viewModelSat.stationPos.observe(viewLifecycleOwner, { renderStationPos(it, binding) })
|
||||
viewModelSat.allSatPositions.observe(viewLifecycleOwner, { renderSatPositions(it, binding) })
|
||||
viewModelSat.satTrack.observe(viewLifecycleOwner, { renderSatTrack(it, binding) })
|
||||
viewModelSat.satFootprint.observe(viewLifecycleOwner, { renderSatFootprint(it, binding) })
|
||||
viewModelSat.satData.observe(viewLifecycleOwner, { renderSatData(it, binding) })
|
||||
}
|
||||
|
||||
private fun renderStationPos(stationPos: Position, binding: FragmentMapBinding) {
|
||||
|
@ -116,7 +116,7 @@ class MapFragment : Fragment(R.layout.fragment_map) {
|
|||
binding.apply {
|
||||
val markers = FolderOverlay()
|
||||
posMap.entries.forEach {
|
||||
if (viewModel.shouldUseTextLabels()) {
|
||||
if (viewModelSat.shouldUseTextLabels()) {
|
||||
Marker(mapView).apply {
|
||||
setInfoWindow(null)
|
||||
textLabelFontSize = 24
|
||||
|
@ -131,7 +131,7 @@ class MapFragment : Fragment(R.layout.fragment_map) {
|
|||
Timber.d(exception)
|
||||
}
|
||||
setOnMarkerClickListener { _, _ ->
|
||||
viewModel.selectSatellite(it.key)
|
||||
viewModelSat.selectSatellite(it.key)
|
||||
return@setOnMarkerClickListener true
|
||||
}
|
||||
markers.add(this)
|
||||
|
@ -147,7 +147,7 @@ class MapFragment : Fragment(R.layout.fragment_map) {
|
|||
Timber.d(exception)
|
||||
}
|
||||
setOnMarkerClickListener { _, _ ->
|
||||
viewModel.selectSatellite(it.key)
|
||||
viewModelSat.selectSatellite(it.key)
|
||||
return@setOnMarkerClickListener true
|
||||
}
|
||||
markers.add(this)
|
|
@ -15,12 +15,12 @@
|
|||
* 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.presentation.mapScreen
|
||||
package com.rtbishop.look4sat.presentation.satMapScreen
|
||||
|
||||
import androidx.lifecycle.*
|
||||
import com.rtbishop.look4sat.data.PreferenceSource
|
||||
import com.rtbishop.look4sat.data.SatelliteRepo
|
||||
import com.rtbishop.look4sat.di.DefaultDispatcher
|
||||
import com.rtbishop.look4sat.data.PreferencesSource
|
||||
import com.rtbishop.look4sat.data.SatDataRepository
|
||||
import com.rtbishop.look4sat.injection.DefaultDispatcher
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Position
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
|
||||
|
@ -35,13 +35,13 @@ import kotlin.math.pow
|
|||
import kotlin.math.sqrt
|
||||
|
||||
@HiltViewModel
|
||||
class MapViewModel @Inject constructor(
|
||||
private val satelliteRepo: SatelliteRepo,
|
||||
private val preferenceSource: PreferenceSource,
|
||||
class SatMapViewModel @Inject constructor(
|
||||
private val satDataRepository: SatDataRepository,
|
||||
private val preferencesSource: PreferencesSource,
|
||||
@DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher
|
||||
) : ViewModel() {
|
||||
|
||||
private val gsp = preferenceSource.loadStationPosition()
|
||||
private val gsp = preferencesSource.loadStationPosition()
|
||||
private var dataUpdateJob: Job? = null
|
||||
private var allSatList = listOf<Satellite>()
|
||||
private lateinit var selectedSat: Satellite
|
||||
|
@ -66,7 +66,7 @@ class MapViewModel @Inject constructor(
|
|||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
satelliteRepo.getSelectedSatellites().also { selectedSatellites ->
|
||||
satDataRepository.getSelectedSatellites().also { selectedSatellites ->
|
||||
if (selectedSatellites.isNotEmpty()) {
|
||||
allSatList = selectedSatellites
|
||||
selectSatellite(selectedSatellites.first())
|
||||
|
@ -76,7 +76,7 @@ class MapViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun shouldUseTextLabels(): Boolean {
|
||||
return preferenceSource.shouldUseTextLabels()
|
||||
return preferencesSource.shouldUseTextLabels()
|
||||
}
|
||||
|
||||
fun scrollSelection(decrement: Boolean) {
|
||||
|
@ -171,13 +171,13 @@ class MapViewModel @Inject constructor(
|
|||
val osmLon = getOsmLon(Math.toDegrees(satPos.longitude))
|
||||
val osmPos = Position(osmLat, osmLon)
|
||||
val qthLoc =
|
||||
preferenceSource.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --"
|
||||
preferencesSource.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --"
|
||||
val velocity = getOrbitalVelocity(satPos.altitude)
|
||||
val satData = SatData(
|
||||
sat, sat.tle.catnum, sat.tle.name, satPos.range,
|
||||
satPos.altitude, velocity, qthLoc, osmPos
|
||||
)
|
||||
this@MapViewModel._satData.postValue(satData)
|
||||
this@SatMapViewModel._satData.postValue(satData)
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.polarScreen
|
||||
package com.rtbishop.look4sat.presentation.satPassInfoScreen
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
|
@ -34,15 +34,15 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
import java.util.*
|
||||
|
||||
@AndroidEntryPoint
|
||||
class PolarFragment : Fragment(R.layout.fragment_polar) {
|
||||
class PassInfoFragment : Fragment(R.layout.fragment_polar) {
|
||||
|
||||
private val viewModel: PolarViewModel by viewModels()
|
||||
private var polarView: PolarView? = null
|
||||
private val viewModel: PassInfoViewModel by viewModels()
|
||||
private var passInfoView: PassInfoView? = null
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
FragmentPolarBinding.bind(view).apply {
|
||||
val transAdapter = TransAdapter()
|
||||
val transAdapter = SatTransAdapter()
|
||||
recycler.apply {
|
||||
setHasFixedSize(true)
|
||||
adapter = transAdapter
|
||||
|
@ -65,27 +65,27 @@ class PolarFragment : Fragment(R.layout.fragment_polar) {
|
|||
viewModel.disableSensor()
|
||||
}
|
||||
|
||||
private fun setupObservers(transAdapter: TransAdapter, binding: FragmentPolarBinding) {
|
||||
private fun setupObservers(satTransAdapter: SatTransAdapter, binding: FragmentPolarBinding) {
|
||||
val catNum = requireArguments().getInt("catNum")
|
||||
val aosTime = requireArguments().getLong("aosTime")
|
||||
viewModel.getPass(catNum, aosTime).observe(viewLifecycleOwner) { pass ->
|
||||
polarView = PolarView(requireContext()).apply { setPass(pass) }
|
||||
binding.frame.addView(polarView)
|
||||
observeTransmitters(pass, transAdapter, binding)
|
||||
passInfoView = PassInfoView(requireContext()).apply { setPass(pass) }
|
||||
binding.frame.addView(passInfoView)
|
||||
observeTransmitters(pass, satTransAdapter, binding)
|
||||
}
|
||||
viewModel.orientation.observe(viewLifecycleOwner, { orientation ->
|
||||
polarView?.setOrientation(orientation.first, orientation.second, orientation.third)
|
||||
passInfoView?.setOrientation(orientation.first, orientation.second, orientation.third)
|
||||
})
|
||||
}
|
||||
|
||||
private fun observeTransmitters(
|
||||
satPass: SatPass,
|
||||
transAdapter: TransAdapter,
|
||||
satTransAdapter: SatTransAdapter,
|
||||
binding: FragmentPolarBinding
|
||||
) {
|
||||
viewModel.transmitters.observe(viewLifecycleOwner, { list ->
|
||||
if (list.isNotEmpty()) {
|
||||
transAdapter.submitList(list)
|
||||
satTransAdapter.submitList(list)
|
||||
binding.recycler.visibility = View.VISIBLE
|
||||
binding.noTransMsg.visibility = View.INVISIBLE
|
||||
} else {
|
||||
|
@ -93,6 +93,7 @@ class PolarFragment : Fragment(R.layout.fragment_polar) {
|
|||
binding.noTransMsg.visibility = View.VISIBLE
|
||||
}
|
||||
setPassText(satPass, binding)
|
||||
passInfoView?.invalidate()
|
||||
})
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.polarScreen
|
||||
package com.rtbishop.look4sat.presentation.satPassInfoScreen
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
|
@ -27,7 +27,7 @@ import java.util.*
|
|||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class PolarView(context: Context) : View(context) {
|
||||
class PassInfoView(context: Context) : View(context) {
|
||||
|
||||
private lateinit var satPass: SatPass
|
||||
private val polarWidth = resources.displayMetrics.widthPixels
|
|
@ -15,13 +15,13 @@
|
|||
* 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.presentation.polarScreen
|
||||
package com.rtbishop.look4sat.presentation.satPassInfoScreen
|
||||
|
||||
import androidx.lifecycle.*
|
||||
import com.rtbishop.look4sat.data.PassesRepo
|
||||
import com.rtbishop.look4sat.data.PreferenceSource
|
||||
import com.rtbishop.look4sat.data.SatelliteRepo
|
||||
import com.rtbishop.look4sat.di.IoDispatcher
|
||||
import com.rtbishop.look4sat.data.SatPassRepository
|
||||
import com.rtbishop.look4sat.data.PreferencesSource
|
||||
import com.rtbishop.look4sat.data.SatDataRepository
|
||||
import com.rtbishop.look4sat.injection.IoDispatcher
|
||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
|
||||
import com.rtbishop.look4sat.framework.OrientationProvider
|
||||
|
@ -35,11 +35,11 @@ import java.util.*
|
|||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class PolarViewModel @Inject constructor(
|
||||
class PassInfoViewModel @Inject constructor(
|
||||
private val orientationProvider: OrientationProvider,
|
||||
private val preferenceSource: PreferenceSource,
|
||||
private val passesRepo: PassesRepo,
|
||||
private val satelliteRepo: SatelliteRepo,
|
||||
private val preferencesSource: PreferencesSource,
|
||||
private val satPassRepository: SatPassRepository,
|
||||
private val satDataRepository: SatDataRepository,
|
||||
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
||||
) : ViewModel(), OrientationProvider.OrientationListener {
|
||||
|
||||
|
@ -49,7 +49,7 @@ class PolarViewModel @Inject constructor(
|
|||
val orientation: LiveData<Triple<Float, Float, Float>> = _orientation
|
||||
|
||||
fun getPass(catNum: Int, aosTime: Long) = liveData {
|
||||
passesRepo.passes.collect { passes ->
|
||||
satPassRepository.passes.collect { passes ->
|
||||
val pass = passes.find { it.catNum == catNum && it.aosDate.time == aosTime }
|
||||
pass?.let { satPass ->
|
||||
processTransmitters(satPass)
|
||||
|
@ -60,20 +60,20 @@ class PolarViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun enableSensor() {
|
||||
if (preferenceSource.shouldUseCompass()) orientationProvider.startListening(this)
|
||||
if (preferencesSource.shouldUseCompass()) orientationProvider.startListening(this)
|
||||
}
|
||||
|
||||
fun disableSensor() {
|
||||
if (preferenceSource.shouldUseCompass()) orientationProvider.stopListening()
|
||||
if (preferencesSource.shouldUseCompass()) orientationProvider.stopListening()
|
||||
}
|
||||
|
||||
override fun onOrientationChanged(azimuth: Float, pitch: Float, roll: Float) {
|
||||
_orientation.value = Triple(azimuth + preferenceSource.getMagDeclination(), pitch, roll)
|
||||
_orientation.value = Triple(azimuth + preferencesSource.getMagDeclination(), pitch, roll)
|
||||
}
|
||||
|
||||
private fun initRotatorControl(satPass: SatPass) {
|
||||
viewModelScope.launch {
|
||||
val rotatorPrefs = preferenceSource.getRotatorServer()
|
||||
val rotatorPrefs = preferencesSource.getRotatorServer()
|
||||
if (rotatorPrefs != null) {
|
||||
runCatching {
|
||||
withContext(ioDispatcher) {
|
||||
|
@ -97,7 +97,7 @@ class PolarViewModel @Inject constructor(
|
|||
|
||||
private fun processTransmitters(satPass: SatPass) {
|
||||
viewModelScope.launch {
|
||||
satelliteRepo.getSatTransmitters(satPass.catNum).collect { transList ->
|
||||
satDataRepository.getSatTransmitters(satPass.catNum).collect { transList ->
|
||||
while (isActive) {
|
||||
val timeNow = Date()
|
||||
val copiedList = transList.map { it.copy() }
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.polarScreen
|
||||
package com.rtbishop.look4sat.presentation.satPassInfoScreen
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
|
@ -27,7 +27,7 @@ import com.rtbishop.look4sat.databinding.ItemTransBinding
|
|||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import java.util.*
|
||||
|
||||
class TransAdapter : RecyclerView.Adapter<TransAdapter.TransHolder>() {
|
||||
class SatTransAdapter : RecyclerView.Adapter<SatTransAdapter.TransHolder>() {
|
||||
|
||||
private val diffCallback = object : DiffUtil.ItemCallback<SatTrans>() {
|
||||
override fun areItemsTheSame(oldItem: SatTrans, newItem: SatTrans): Boolean {
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.passesScreen
|
||||
package com.rtbishop.look4sat.presentation.satPassScreen
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
|
@ -29,7 +29,7 @@ import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
|
|||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class PassesAdapter(private val isUTC: Boolean, private val clickListener: PassesClickListener) :
|
||||
class SatPassAdapter(private val isUTC: Boolean, private val clickListener: PassesClickListener) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val diffCallback = object : DiffUtil.ItemCallback<SatPass>() {
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.presentation.passesScreen
|
||||
package com.rtbishop.look4sat.presentation.satPassScreen
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
|
@ -36,9 +36,9 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
import java.util.*
|
||||
|
||||
@AndroidEntryPoint
|
||||
class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesClickListener {
|
||||
class SatPassFragment : Fragment(R.layout.fragment_passes), SatPassAdapter.PassesClickListener {
|
||||
|
||||
private val viewModel: PassesViewModel by viewModels()
|
||||
private val viewModel: SatPassViewModel by viewModels()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
@ -46,7 +46,7 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
|
|||
}
|
||||
|
||||
private fun setupComponents(view: View) {
|
||||
val passesAdapter = PassesAdapter(viewModel.shouldUseUTC(), this)
|
||||
val passesAdapter = SatPassAdapter(viewModel.shouldUseUTC(), this)
|
||||
val binding = FragmentPassesBinding.bind(view).apply {
|
||||
passesRecycler.apply {
|
||||
setHasFixedSize(true)
|
||||
|
@ -65,12 +65,12 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
|
|||
|
||||
private fun handleNewPasses(
|
||||
result: Result<List<SatPass>>,
|
||||
passesAdapter: PassesAdapter,
|
||||
satPassAdapter: SatPassAdapter,
|
||||
binding: FragmentPassesBinding
|
||||
) {
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
passesAdapter.submitList(result.data)
|
||||
satPassAdapter.submitList(result.data)
|
||||
binding.apply {
|
||||
passesError.visibility = View.INVISIBLE
|
||||
passesProgress.visibility = View.INVISIBLE
|
|
@ -15,16 +15,16 @@
|
|||
* 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.presentation.passesScreen
|
||||
package com.rtbishop.look4sat.presentation.satPassScreen
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.rtbishop.look4sat.data.PassesRepo
|
||||
import com.rtbishop.look4sat.data.SatelliteRepo
|
||||
import com.rtbishop.look4sat.data.PreferencesSource
|
||||
import com.rtbishop.look4sat.data.SatDataRepository
|
||||
import com.rtbishop.look4sat.data.SatPassRepository
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
|
||||
import com.rtbishop.look4sat.framework.PreferencesProvider
|
||||
import com.rtbishop.look4sat.framework.model.Result
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.*
|
||||
|
@ -32,10 +32,10 @@ import kotlinx.coroutines.flow.collect
|
|||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class PassesViewModel @Inject constructor(
|
||||
private val satelliteRepo: SatelliteRepo,
|
||||
private val passesRepo: PassesRepo,
|
||||
private val preferenceSource: PreferencesProvider
|
||||
class SatPassViewModel @Inject constructor(
|
||||
private val satDataRepository: SatDataRepository,
|
||||
private val satPassRepository: SatPassRepository,
|
||||
private val preferenceSource: PreferencesSource
|
||||
) : ViewModel() {
|
||||
|
||||
private val _passes = MutableLiveData<Result<List<SatPass>>>(Result.InProgress)
|
||||
|
@ -45,10 +45,10 @@ class PassesViewModel @Inject constructor(
|
|||
init {
|
||||
viewModelScope.launch {
|
||||
_passes.postValue(Result.InProgress)
|
||||
passesRepo.triggerCalculation(satelliteRepo.getSelectedSatellites())
|
||||
satPassRepository.triggerCalculation(satDataRepository.getSelectedSatellites())
|
||||
}
|
||||
viewModelScope.launch {
|
||||
passesRepo.passes.collect { passes ->
|
||||
satPassRepository.passes.collect { passes ->
|
||||
passesProcessing?.cancelAndJoin()
|
||||
passesProcessing = viewModelScope.launch { tickPasses(passes) }
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ class PassesViewModel @Inject constructor(
|
|||
viewModelScope.launch {
|
||||
_passes.postValue(Result.InProgress)
|
||||
passesProcessing?.cancelAndJoin()
|
||||
passesRepo.forceCalculation(satelliteRepo.getSelectedSatellites())
|
||||
satPassRepository.forceCalculation(satDataRepository.getSelectedSatellites())
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".presentation.infoScreen.InfoFragment">
|
||||
tools:context=".presentation.appInfoScreen.AppInfoFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<fragment
|
||||
android:id="@+id/nav_entries"
|
||||
android:name="com.rtbishop.look4sat.presentation.entriesScreen.EntriesFragment"
|
||||
android:name="com.rtbishop.look4sat.presentation.satItemScreen.SatItemFragment"
|
||||
tools:layout="@layout/fragment_entries">
|
||||
<action
|
||||
android:id="@+id/action_entries_to_passes"
|
||||
|
@ -20,7 +20,7 @@
|
|||
|
||||
<fragment
|
||||
android:id="@+id/nav_passes"
|
||||
android:name="com.rtbishop.look4sat.presentation.passesScreen.PassesFragment"
|
||||
android:name="com.rtbishop.look4sat.presentation.satPassScreen.SatPassFragment"
|
||||
tools:layout="@layout/fragment_passes">
|
||||
<action
|
||||
android:id="@+id/action_passes_to_polar"
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
<fragment
|
||||
android:id="@+id/nav_polar"
|
||||
android:name="com.rtbishop.look4sat.presentation.polarScreen.PolarFragment"
|
||||
android:name="com.rtbishop.look4sat.presentation.satPassInfoScreen.PassInfoFragment"
|
||||
tools:layout="@layout/fragment_polar">
|
||||
<action
|
||||
android:id="@+id/action_polar_to_passes"
|
||||
|
@ -48,20 +48,20 @@
|
|||
|
||||
<fragment
|
||||
android:id="@+id/nav_map"
|
||||
android:name="com.rtbishop.look4sat.presentation.mapScreen.MapFragment"
|
||||
android:name="com.rtbishop.look4sat.presentation.satMapScreen.SatMapFragment"
|
||||
tools:layout="@layout/fragment_map" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_prefs"
|
||||
android:name="com.rtbishop.look4sat.presentation.prefsScreen.PrefsFragment" />
|
||||
android:name="com.rtbishop.look4sat.presentation.appSettingsScreen.AppSettingsFragment" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_info"
|
||||
android:name="com.rtbishop.look4sat.presentation.infoScreen.InfoFragment"
|
||||
android:name="com.rtbishop.look4sat.presentation.appInfoScreen.AppInfoFragment"
|
||||
tools:layout="@layout/fragment_info" />
|
||||
<dialog
|
||||
android:id="@+id/nav_dialog_splash"
|
||||
android:name="com.rtbishop.look4sat.presentation.splashDialog.SplashDialog"
|
||||
android:name="com.rtbishop.look4sat.presentation.appSplashDialog.AppSplashDialog"
|
||||
tools:layout="@layout/dialog_splash" />
|
||||
|
||||
</navigation>
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.rtbishop.look4sat.data
|
|||
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
|
||||
|
||||
interface PreferenceSource {
|
||||
interface PreferencesSource {
|
||||
|
||||
fun positionToQTH(lat: Double, lon: Double): String?
|
||||
|
|
@ -6,7 +6,7 @@ import com.rtbishop.look4sat.domain.model.SatTrans
|
|||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface LocalDataSource {
|
||||
interface SatDataLocalSource {
|
||||
|
||||
fun getSatItems(): Flow<List<SatItem>>
|
||||
|
|
@ -3,7 +3,7 @@ package com.rtbishop.look4sat.data
|
|||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import java.io.InputStream
|
||||
|
||||
interface RemoteDataSource {
|
||||
interface SatDataRemoteSource {
|
||||
|
||||
suspend fun fetchDataStream(url: String): InputStream?
|
||||
|
|
@ -12,9 +12,10 @@ import kotlinx.coroutines.withContext
|
|||
import java.io.InputStream
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
class SatelliteRepo(
|
||||
private val localSource: LocalDataSource,
|
||||
private val remoteSource: RemoteDataSource,
|
||||
class SatDataRepository(
|
||||
private val preferencesSource: PreferencesSource,
|
||||
private val satLocalSource: SatDataLocalSource,
|
||||
private val satRemoteSource: SatDataRemoteSource,
|
||||
private val ioDispatcher: CoroutineDispatcher
|
||||
) {
|
||||
private val defaultSources = listOf(
|
||||
|
@ -24,20 +25,40 @@ class SatelliteRepo(
|
|||
"https://www.prismnet.com/~mmccants/tles/inttles.zip"
|
||||
)
|
||||
|
||||
private val transmittersModes = arrayOf(
|
||||
"AFSK", "AFSK S-Net", "AFSK SALSAT", "AHRPT", "AM", "APT", "BPSK", "BPSK PMT-A3",
|
||||
"CERTO", "CW", "DQPSK", "DSTAR", "DUV", "FFSK", "FM", "FMN", "FSK", "FSK AX.100 Mode 5",
|
||||
"FSK AX.100 Mode 6", "FSK AX.25 G3RUH", "GFSK", "GFSK Rktr", "GMSK", "HRPT", "LoRa",
|
||||
"LRPT", "LSB", "MFSK", "MSK", "MSK AX.100 Mode 5", "MSK AX.100 Mode 6", "OFDM", "OQPSK",
|
||||
"PSK", "PSK31", "PSK63", "QPSK", "QPSK31", "QPSK63", "SSTV", "USB", "WSJT"
|
||||
)
|
||||
|
||||
fun getAllModes(): Array<String> {
|
||||
return transmittersModes
|
||||
}
|
||||
|
||||
fun saveModesSelection(modes: List<String>) {
|
||||
preferencesSource.saveModesSelection(modes)
|
||||
}
|
||||
|
||||
fun loadModesSelection(): List<String> {
|
||||
return preferencesSource.loadModesSelection()
|
||||
}
|
||||
|
||||
fun getSatItems(): Flow<List<SatItem>> {
|
||||
return localSource.getSatItems()
|
||||
return satLocalSource.getSatItems()
|
||||
}
|
||||
|
||||
fun getSatTransmitters(catNum: Int): Flow<List<SatTrans>> {
|
||||
return localSource.getSatTransmitters(catNum)
|
||||
return satLocalSource.getSatTransmitters(catNum)
|
||||
}
|
||||
|
||||
suspend fun getSelectedSatellites(): List<Satellite> {
|
||||
return localSource.getSelectedSatellites()
|
||||
return satLocalSource.getSelectedSatellites()
|
||||
}
|
||||
|
||||
suspend fun updateEntriesFromFile(stream: InputStream) = withContext(ioDispatcher) {
|
||||
localSource.updateEntries(importSatEntries(stream))
|
||||
satLocalSource.updateEntries(importSatEntries(stream))
|
||||
}
|
||||
|
||||
suspend fun updateEntriesFromWeb(sources: List<String> = defaultSources) {
|
||||
|
@ -46,7 +67,7 @@ class SatelliteRepo(
|
|||
val streams = mutableListOf<InputStream>()
|
||||
val entries = mutableListOf<SatEntry>()
|
||||
sources.forEach { source ->
|
||||
remoteSource.fetchDataStream(source)?.let { stream ->
|
||||
satRemoteSource.fetchDataStream(source)?.let { stream ->
|
||||
if (source.contains(".zip", true)) {
|
||||
val zipStream = ZipInputStream(stream).apply { nextEntry }
|
||||
streams.add(zipStream)
|
||||
|
@ -56,17 +77,17 @@ class SatelliteRepo(
|
|||
}
|
||||
}
|
||||
streams.forEach { stream -> entries.addAll(importSatEntries(stream)) }
|
||||
localSource.updateEntries(entries)
|
||||
satLocalSource.updateEntries(entries)
|
||||
}
|
||||
launch(ioDispatcher) {
|
||||
val transmitters = remoteSource.fetchTransmitters().filter { it.isAlive }
|
||||
localSource.updateTransmitters(transmitters)
|
||||
val transmitters = satRemoteSource.fetchTransmitters().filter { it.isAlive }
|
||||
satLocalSource.updateTransmitters(transmitters)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
|
||||
localSource.updateEntriesSelection(catNums, isSelected)
|
||||
satLocalSource.updateEntriesSelection(catNums, isSelected)
|
||||
}
|
||||
|
||||
private fun importSatEntries(stream: InputStream): List<SatEntry> {
|
|
@ -25,8 +25,8 @@ import kotlinx.coroutines.flow.SharedFlow
|
|||
import kotlinx.coroutines.withContext
|
||||
import java.util.*
|
||||
|
||||
class PassesRepo(
|
||||
private val preferenceSource: PreferenceSource,
|
||||
class SatPassRepository(
|
||||
private val preferencesSource: PreferencesSource,
|
||||
private val defaultDispatcher: CoroutineDispatcher
|
||||
) {
|
||||
private val _passes = MutableSharedFlow<List<SatPass>>(replay = 1)
|
||||
|
@ -57,15 +57,15 @@ class PassesRepo(
|
|||
}
|
||||
|
||||
private fun getPasses(satellite: Satellite, refDate: Date): List<SatPass> {
|
||||
val predictor = satellite.getPredictor(preferenceSource.loadStationPosition())
|
||||
return predictor.getPasses(refDate, preferenceSource.getHoursAhead(), true)
|
||||
val predictor = satellite.getPredictor(preferencesSource.loadStationPosition())
|
||||
return predictor.getPasses(refDate, preferencesSource.getHoursAhead(), true)
|
||||
}
|
||||
|
||||
private fun filterPasses(passes: List<SatPass>, refDate: Date): List<SatPass> {
|
||||
val timeFuture = Date(refDate.time + (preferenceSource.getHoursAhead() * 3600 * 1000))
|
||||
val timeFuture = Date(refDate.time + (preferencesSource.getHoursAhead() * 3600 * 1000))
|
||||
return passes.filter { it.losDate.after(refDate) }
|
||||
.filter { it.aosDate.before(timeFuture) }
|
||||
.filter { it.maxElevation > preferenceSource.getMinElevation() }
|
||||
.filter { it.maxElevation > preferencesSource.getMinElevation() }
|
||||
.sortedBy { it.aosDate }
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue