Enabled data update progress indicator

This commit is contained in:
Arty Bishop committed 2022-02-07 16:01:40 +00:00
1 parent 61cbc212b5
commit 9b38e2c63e
5 files changed
+123 -82

No files matched your search

@@ -19,73 +19,92 @@ 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 fun setDataUpdateHandled() {
_updateState.value = DataState.Handled
}
override fun updateDataFromFile(stream: InputStream) {
repositoryScope.launch(exceptionHandler) {
_updateState.value = DataState.Loading
val importedSatellites = importSatellites(stream)
localSource.updateEntries(importedSatellites)
_updateState.value = DataState.Success(0L)
}
}
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?>()
val streams = mutableListOf<InputStream>()
val entries = mutableListOf<SatEntry>()
sources.forEach { jobsMap[it] = async { remoteSource.fetchFileStream(it) } }
jobsMap.forEach { streamsMap[it.key] = it.value.await() }
streamsMap.forEach { stream ->
stream.value?.let { inputStream ->
when {
stream.key.contains("=csv", true) -> {
val tles = dataParser.parseCSVStream(inputStream)
entries.addAll(tles.map { tle -> SatEntry(tle) })
}
stream.key.contains(".zip", true) -> {
streams.add(ZipInputStream(inputStream).apply { nextEntry })
}
else -> streams.add(inputStream)
}
}
}
streams.forEach { stream -> entries.addAll(importSatellites(stream)) }
localSource.updateEntries(entries)
}
println("Update from web took $updateTimeMillis ms")
_updateState.value = DataState.Success(updateTimeMillis)
}
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 updateDataFromFile(stream: InputStream) {
localSource.updateEntries(importSatellites(stream))
}
override suspend fun updateDataFromWeb(sources: List<String>) {
coroutineScope {
launch {
settingsHandler.saveDataSources(sources)
}
launch {
val updateTimeMillis = measureTimeMillis {
val jobsMap = mutableMapOf<String, Deferred<InputStream?>>()
val streamsMap = mutableMapOf<String, InputStream?>()
val streams = mutableListOf<InputStream>()
val entries = mutableListOf<SatEntry>()
sources.forEach { jobsMap[it] = async { remoteSource.fetchFileStream(it) } }
jobsMap.forEach { streamsMap[it.key] = it.value.await() }
streamsMap.forEach { stream ->
stream.value?.let { inputStream ->
when {
stream.key.contains("=csv", true) -> {
val tles = dataParser.parseCSVStream(inputStream)
entries.addAll(tles.map { tle -> SatEntry(tle) })
}
stream.key.contains(".zip", true) -> {
streams.add(ZipInputStream(inputStream).apply { nextEntry })
}
else -> streams.add(inputStream)
}
}
}
streams.forEach { stream -> entries.addAll(importSatellites(stream)) }
localSource.updateEntries(entries)
}
println("Update from web took $updateTimeMillis ms")
}
launch {
remoteSource.fetchFileStream(settingsHandler.transmittersSource)?.let { stream ->
val transmitters = dataParser.parseJSONStream(stream)
localSource.updateTransmitters(transmitters)
}
}
}
}
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)
}