mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Enabled data update progress indicator
This commit is contained in:
1 parent
61cbc212b5
commit
9b38e2c63e
5 files changed
+91
-50
No files matched your search
@@ -37,6 +37,8 @@ import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@@ -46,7 +48,7 @@ object CoreModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSatelliteRepo(
|
||||
settingsHandler: ISettingsHandler,
|
||||
settings: ISettingsHandler,
|
||||
@ApplicationContext context: Context,
|
||||
@IoDispatcher ioDispatcher: CoroutineDispatcher,
|
||||
@DefaultDispatcher defaultDispatcher: CoroutineDispatcher
|
||||
@@ -57,7 +59,8 @@ object CoreModule {
|
||||
.fallbackToDestructiveMigration().build()
|
||||
val localSource = LocalSource(db.entriesDao(), db.transmittersDao())
|
||||
val remoteSource = RemoteSource(ioDispatcher)
|
||||
return DataRepository(dataParser, localSource, remoteSource, settingsHandler)
|
||||
val repositoryScope = CoroutineScope(SupervisorJob())
|
||||
return DataRepository(dataParser, settings, localSource, remoteSource, repositoryScope)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
+26
-4
@@ -56,7 +56,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
|
||||
}
|
||||
private val contentContract = ActivityResultContracts.GetContent()
|
||||
private val contentRequest = registerForActivityResult(contentContract) { uri ->
|
||||
viewModel.updateDataFromFile(uri)
|
||||
uri?.let { viewModel.updateDataFromFile(uri) }
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@@ -70,7 +70,10 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
|
||||
setupOtherCard(settingsBinding)
|
||||
setupWarrantyCard(settingsBinding)
|
||||
viewModel.stationPosition.asLiveData().observe(viewLifecycleOwner) { stationPos ->
|
||||
stationPos?.let { handleStationPosition(it, settingsBinding) }
|
||||
stationPos?.let { handleStationPosition(stationPos, settingsBinding) }
|
||||
}
|
||||
viewModel.getUpdateState().asLiveData().observe(viewLifecycleOwner) { updateState ->
|
||||
updateState?.let { handleSatState(updateState, settingsBinding) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,13 +174,13 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
|
||||
is DataState.Success -> {
|
||||
setPositionText(pos.data, binding)
|
||||
binding.prefsLocation.locationProgress.isIndeterminate = false
|
||||
showToast(getString(R.string.pref_pos_success))
|
||||
viewModel.setPositionHandled()
|
||||
showToast(getString(R.string.pref_pos_success))
|
||||
}
|
||||
is DataState.Error -> {
|
||||
binding.prefsLocation.locationProgress.isIndeterminate = false
|
||||
showToast(pos.message.toString())
|
||||
viewModel.setPositionHandled()
|
||||
showToast(pos.message.toString())
|
||||
}
|
||||
DataState.Loading -> {
|
||||
binding.prefsLocation.locationProgress.isIndeterminate = true
|
||||
@@ -186,6 +189,25 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSatState(state: DataState<Long>, binding: FragmentSettingsBinding) {
|
||||
when (state) {
|
||||
is DataState.Success -> {
|
||||
binding.prefsData.updateProgress.isIndeterminate = false
|
||||
viewModel.setUpdateHandled()
|
||||
showToast("Data updated successfully")
|
||||
}
|
||||
is DataState.Error -> {
|
||||
binding.prefsData.updateProgress.isIndeterminate = false
|
||||
viewModel.setUpdateHandled()
|
||||
showToast(state.message.toString())
|
||||
}
|
||||
is DataState.Loading -> {
|
||||
binding.prefsData.updateProgress.isIndeterminate = true
|
||||
}
|
||||
is DataState.Handled -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showToast(message: String) {
|
||||
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
+11
-20
@@ -10,7 +10,6 @@ import com.rtbishop.look4sat.domain.ILocationHandler
|
||||
import com.rtbishop.look4sat.domain.model.DataState
|
||||
import com.rtbishop.look4sat.domain.predict.GeoPos
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
@@ -21,14 +20,10 @@ class SettingsViewModel @Inject constructor(
|
||||
private val settings: ISettingsHandler,
|
||||
private val repository: IDataRepository,
|
||||
private val locationHandler: ILocationHandler
|
||||
) : ViewModel(), ILocationHandler {
|
||||
|
||||
private val exceptionHandler = CoroutineExceptionHandler { _, exception ->
|
||||
println("Handled $exception in CoroutineExceptionHandler")
|
||||
}
|
||||
) : ViewModel() {
|
||||
|
||||
fun updateDataFromFile(uri: Uri) {
|
||||
viewModelScope.launch(exceptionHandler) {
|
||||
viewModelScope.launch {
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
resolver.openInputStream(uri)?.use { fileUri ->
|
||||
repository.updateDataFromFile(fileUri)
|
||||
@@ -37,10 +32,8 @@ class SettingsViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun updateDataFromWeb(sources: List<String>) {
|
||||
viewModelScope.launch(exceptionHandler) {
|
||||
repository.updateDataFromWeb(sources)
|
||||
}
|
||||
}
|
||||
|
||||
fun getUseUTC(): Boolean = settings.getUseUTC()
|
||||
|
||||
@@ -66,21 +59,19 @@ class SettingsViewModel @Inject constructor(
|
||||
|
||||
fun setRotatorPort(value: String) = settings.setRotatorPort(value)
|
||||
|
||||
override val stationPosition: SharedFlow<DataState<GeoPos>> = locationHandler.stationPosition
|
||||
fun getUpdateState() = repository.dataUpdateState
|
||||
|
||||
override fun getStationPosition(): GeoPos = locationHandler.getStationPosition()
|
||||
fun setUpdateHandled() = repository.setDataUpdateHandled()
|
||||
|
||||
override fun setStationPosition(latitude: Double, longitude: Double) {
|
||||
locationHandler.setStationPosition(latitude, longitude)
|
||||
}
|
||||
val stationPosition: SharedFlow<DataState<GeoPos>> = locationHandler.stationPosition
|
||||
|
||||
override fun setPositionFromGps() = locationHandler.setPositionFromGps()
|
||||
fun getStationPosition(): GeoPos = locationHandler.getStationPosition()
|
||||
|
||||
override fun setPositionFromNet() = locationHandler.setPositionFromNet()
|
||||
fun setPositionFromGps() = locationHandler.setPositionFromGps()
|
||||
|
||||
override fun setPositionFromQth(qthString: String) {
|
||||
locationHandler.setPositionFromQth(qthString)
|
||||
}
|
||||
fun setPositionFromNet() = locationHandler.setPositionFromNet()
|
||||
|
||||
override fun setPositionHandled() = locationHandler.setPositionHandled()
|
||||
fun setPositionFromQth(qthString: String) = locationHandler.setPositionFromQth(qthString)
|
||||
|
||||
fun setPositionHandled() = locationHandler.setPositionHandled()
|
||||
}
|
||||
@@ -19,38 +19,51 @@ package com.rtbishop.look4sat.data
|
||||
|
||||
import com.rtbishop.look4sat.domain.DataParser
|
||||
import com.rtbishop.look4sat.domain.IDataRepository
|
||||
import com.rtbishop.look4sat.domain.model.DataState
|
||||
import com.rtbishop.look4sat.domain.model.SatEntry
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import java.io.InputStream
|
||||
import java.util.zip.ZipInputStream
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
class DataRepository(
|
||||
private val dataParser: DataParser,
|
||||
private val settings: ISettingsHandler,
|
||||
private val localSource: ILocalSource,
|
||||
private val remoteSource: IRemoteSource,
|
||||
private val settingsHandler: ISettingsHandler
|
||||
private val repositoryScope: CoroutineScope
|
||||
) : IDataRepository {
|
||||
|
||||
override fun getSatelliteItems() = localSource.getSatelliteItems()
|
||||
private val exceptionHandler = CoroutineExceptionHandler { _, exception ->
|
||||
println("DataRepository: handled $exception")
|
||||
_updateState.value = DataState.Error(exception.message)
|
||||
}
|
||||
private val _updateState = MutableStateFlow<DataState<Long>>(DataState.Handled)
|
||||
override val dataUpdateState: StateFlow<DataState<Long>> = _updateState
|
||||
|
||||
override suspend fun getSelectedSatellites() = localSource.getSelectedSatellites()
|
||||
|
||||
override suspend fun getTransmitters(catnum: Int) = localSource.getTransmitters(catnum)
|
||||
|
||||
override suspend fun updateDataFromFile(stream: InputStream) {
|
||||
localSource.updateEntries(importSatellites(stream))
|
||||
override fun setDataUpdateHandled() {
|
||||
_updateState.value = DataState.Handled
|
||||
}
|
||||
|
||||
override suspend fun updateDataFromWeb(sources: List<String>) {
|
||||
coroutineScope {
|
||||
launch {
|
||||
settingsHandler.saveDataSources(sources)
|
||||
override fun updateDataFromFile(stream: InputStream) {
|
||||
repositoryScope.launch(exceptionHandler) {
|
||||
_updateState.value = DataState.Loading
|
||||
val importedSatellites = importSatellites(stream)
|
||||
localSource.updateEntries(importedSatellites)
|
||||
_updateState.value = DataState.Success(0L)
|
||||
}
|
||||
launch {
|
||||
}
|
||||
|
||||
override fun updateDataFromWeb(sources: List<String>) {
|
||||
_updateState.value = DataState.Loading
|
||||
repositoryScope.launch(exceptionHandler) {
|
||||
settings.saveDataSources(sources)
|
||||
}
|
||||
repositoryScope.launch(exceptionHandler) {
|
||||
val updateTimeMillis = measureTimeMillis {
|
||||
val jobsMap = mutableMapOf<String, Deferred<InputStream?>>()
|
||||
val streamsMap = mutableMapOf<String, InputStream?>()
|
||||
@@ -76,15 +89,21 @@ class DataRepository(
|
||||
localSource.updateEntries(entries)
|
||||
}
|
||||
println("Update from web took $updateTimeMillis ms")
|
||||
_updateState.value = DataState.Success(updateTimeMillis)
|
||||
}
|
||||
launch {
|
||||
remoteSource.fetchFileStream(settingsHandler.transmittersSource)?.let { stream ->
|
||||
repositoryScope.launch(exceptionHandler) {
|
||||
remoteSource.fetchFileStream(settings.transmittersSource)?.let { stream ->
|
||||
val transmitters = dataParser.parseJSONStream(stream)
|
||||
localSource.updateTransmitters(transmitters)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSatelliteItems(): Flow<List<SatItem>> = localSource.getSatelliteItems()
|
||||
|
||||
override suspend fun getSelectedSatellites() = localSource.getSelectedSatellites()
|
||||
|
||||
override suspend fun getTransmitters(catnum: Int) = localSource.getTransmitters(catnum)
|
||||
|
||||
override suspend fun updateSelection(catnums: List<Int>, isSelected: Boolean) {
|
||||
localSource.updateEntriesSelection(catnums, isSelected)
|
||||
|
||||
@@ -17,23 +17,29 @@
|
||||
*/
|
||||
package com.rtbishop.look4sat.domain
|
||||
|
||||
import com.rtbishop.look4sat.domain.model.DataState
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
import com.rtbishop.look4sat.domain.model.Transmitter
|
||||
import com.rtbishop.look4sat.domain.predict.Satellite
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import java.io.InputStream
|
||||
|
||||
interface IDataRepository {
|
||||
|
||||
val dataUpdateState: StateFlow<DataState<Long>>
|
||||
|
||||
fun setDataUpdateHandled()
|
||||
|
||||
fun updateDataFromFile(stream: InputStream)
|
||||
|
||||
fun updateDataFromWeb(sources: List<String>)
|
||||
|
||||
fun getSatelliteItems(): Flow<List<SatItem>>
|
||||
|
||||
suspend fun getSelectedSatellites(): List<Satellite>
|
||||
|
||||
suspend fun getTransmitters(catnum: Int): List<Transmitter>
|
||||
|
||||
suspend fun updateDataFromFile(stream: InputStream)
|
||||
|
||||
suspend fun updateDataFromWeb(sources: List<String>)
|
||||
|
||||
suspend fun updateSelection(catnums: List<Int>, isSelected: Boolean = true)
|
||||
}
|
||||
Reference in new issue
Block a user