mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Created SelectionRepository, cleaned up code
This commit is contained in:
1 parent
5d2a870319
commit
208c587ddf
12 files changed
+156
-130
No files matched your search
@@ -9,6 +9,7 @@ import androidx.room.Room
|
|||||||
import com.rtbishop.look4sat.data.DataParser
|
import com.rtbishop.look4sat.data.DataParser
|
||||||
import com.rtbishop.look4sat.data.DataRepository
|
import com.rtbishop.look4sat.data.DataRepository
|
||||||
import com.rtbishop.look4sat.data.SatelliteRepository
|
import com.rtbishop.look4sat.data.SatelliteRepository
|
||||||
|
import com.rtbishop.look4sat.data.SelectionRepository
|
||||||
import com.rtbishop.look4sat.domain.IDataRepository
|
import com.rtbishop.look4sat.domain.IDataRepository
|
||||||
import com.rtbishop.look4sat.domain.ISatelliteRepository
|
import com.rtbishop.look4sat.domain.ISatelliteRepository
|
||||||
import com.rtbishop.look4sat.domain.ISensorRepository
|
import com.rtbishop.look4sat.domain.ISensorRepository
|
||||||
@@ -58,6 +59,10 @@ class MainContainer(private val context: Context) {
|
|||||||
return DataRepository(parser, fileSource, entries, radios, remoteSource, scope, settings)
|
return DataRepository(parser, fileSource, entries, radios, remoteSource, scope, settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun provideSelectionRepository(): SelectionRepository {
|
||||||
|
return SelectionRepository(Dispatchers.Default, dataRepository, settingsRepository)
|
||||||
|
}
|
||||||
|
|
||||||
private fun provideSensorRepository(): ISensorRepository {
|
private fun provideSensorRepository(): ISensorRepository {
|
||||||
val manager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
val manager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||||
val sensor = manager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
|
val sensor = manager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ interface EntriesDao {
|
|||||||
@Query("SELECT COUNT(*) FROM entries")
|
@Query("SELECT COUNT(*) FROM entries")
|
||||||
fun getEntriesTotal(): Flow<Int>
|
fun getEntriesTotal(): Flow<Int>
|
||||||
|
|
||||||
@Transaction
|
// @Transaction
|
||||||
@Query("SELECT catnum, name FROM entries ORDER BY name ASC")
|
@Query("SELECT catnum, name FROM entries ORDER BY name ASC")
|
||||||
suspend fun getEntriesWithModes(): List<SatItem>
|
suspend fun getEntriesList(): List<SatItem>
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM entries WHERE catnum IN (:selectedIds)")
|
@Query("SELECT * FROM entries WHERE catnum IN (:selectedIds)")
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ class EntriesStorage(private val entriesDao: EntriesDao) : IEntriesStorage {
|
|||||||
|
|
||||||
override fun getEntriesTotal() = entriesDao.getEntriesTotal()
|
override fun getEntriesTotal() = entriesDao.getEntriesTotal()
|
||||||
|
|
||||||
override suspend fun getEntriesWithModes(): List<DomainItem> {
|
override suspend fun getEntriesList(): List<DomainItem> {
|
||||||
return entriesDao.getEntriesWithModes().toDomainItems()
|
return entriesDao.getEntriesList().toDomainItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getEntriesWithIds(ids: List<Int>): List<Satellite> {
|
override suspend fun getEntriesWithIds(ids: List<Int>): List<Satellite> {
|
||||||
@@ -50,7 +50,7 @@ class EntriesStorage(private val entriesDao: EntriesDao) : IEntriesStorage {
|
|||||||
|
|
||||||
private fun DomainEntry.toFramework() = FrameworkEntry(this.data, this.comment)
|
private fun DomainEntry.toFramework() = FrameworkEntry(this.data, this.comment)
|
||||||
|
|
||||||
private fun FrameworkItem.toDomain() = DomainItem(this.catnum, this.name, this.modes, false)
|
private fun FrameworkItem.toDomain() = DomainItem(this.catnum, this.name, false)
|
||||||
|
|
||||||
private fun List<DomainEntry>.toFrameworkEntries() = this.map { entry -> entry.toFramework() }
|
private fun List<DomainEntry>.toFrameworkEntries() = this.map { entry -> entry.toFramework() }
|
||||||
|
|
||||||
|
|||||||
@@ -17,16 +17,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.framework.model
|
package com.rtbishop.look4sat.framework.model
|
||||||
|
|
||||||
import androidx.room.Relation
|
|
||||||
|
|
||||||
data class SatItem(
|
data class SatItem(
|
||||||
val catnum: Int,
|
val catnum: Int,
|
||||||
val name: String,
|
val name: String
|
||||||
@Relation(
|
// @Relation(
|
||||||
parentColumn = "catnum",
|
// parentColumn = "catnum",
|
||||||
entity = SatRadio::class,
|
// entity = SatRadio::class,
|
||||||
entityColumn = "catnum",
|
// entityColumn = "catnum",
|
||||||
projection = ["mode"]
|
// projection = ["mode"]
|
||||||
)
|
// )
|
||||||
val modes: List<String>
|
// val modes: List<String>
|
||||||
)
|
)
|
||||||
@@ -9,7 +9,6 @@ import androidx.compose.foundation.lazy.items
|
|||||||
import androidx.compose.foundation.text.BasicTextField
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@@ -26,7 +25,6 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.rtbishop.look4sat.R
|
import com.rtbishop.look4sat.R
|
||||||
import com.rtbishop.look4sat.model.DataState
|
|
||||||
import com.rtbishop.look4sat.model.SatItem
|
import com.rtbishop.look4sat.model.SatItem
|
||||||
import com.rtbishop.look4sat.presentation.CardIcon
|
import com.rtbishop.look4sat.presentation.CardIcon
|
||||||
import com.rtbishop.look4sat.presentation.CardLoadingIndicator
|
import com.rtbishop.look4sat.presentation.CardLoadingIndicator
|
||||||
@@ -37,25 +35,33 @@ import com.rtbishop.look4sat.presentation.onClick
|
|||||||
@Composable
|
@Composable
|
||||||
fun EntriesScreen(navToPasses: () -> Unit) {
|
fun EntriesScreen(navToPasses: () -> Unit) {
|
||||||
val viewModel = viewModel(EntriesViewModel::class.java, factory = EntriesViewModel.Factory)
|
val viewModel = viewModel(EntriesViewModel::class.java, factory = EntriesViewModel.Factory)
|
||||||
val state = viewModel.satData.collectAsState(initial = DataState.Loading)
|
val uiState = viewModel.uiState.value
|
||||||
|
|
||||||
val showDialog = rememberSaveable { mutableStateOf(false) }
|
val showDialog = rememberSaveable { mutableStateOf(false) }
|
||||||
val toggleDialog = { showDialog.value = showDialog.value.not() }
|
val toggleDialog = { showDialog.value = showDialog.value.not() }
|
||||||
if (showDialog.value) {
|
if (showDialog.value) {
|
||||||
TypesDialog(list = viewModel.satTypes, selected = viewModel.getSatType(), toggleDialog) {
|
TypesDialog(list = uiState.typesList, selected = uiState.currentType, toggleDialog) {
|
||||||
viewModel.setSatType(it)
|
viewModel.setType(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val unselectAll = { viewModel.selectCurrentItems(false) }
|
val unselectAll = { viewModel.updateSelection(false) }
|
||||||
val selectAll = { viewModel.selectCurrentItems(true) }
|
val selectAll = { viewModel.updateSelection(true) }
|
||||||
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||||
TopBar(setQuery = { newQuery: String -> viewModel.setQuery(newQuery) }, saveSelection = {
|
TopBar(setQuery = { newQuery: String -> viewModel.setQuery(newQuery) }, saveSelection = {
|
||||||
viewModel.saveSelection()
|
viewModel.saveSelection()
|
||||||
navToPasses()
|
navToPasses()
|
||||||
})
|
})
|
||||||
MiddleBar(viewModel.getSatType(), { toggleDialog() }, { unselectAll() }, { selectAll() })
|
MiddleBar(uiState.currentType, { toggleDialog() }, { unselectAll() }, { selectAll() })
|
||||||
EntriesCard(state = state.value) { list, value -> viewModel.updateSelection(list, value) }
|
ElevatedCard(modifier = Modifier.fillMaxSize()) {
|
||||||
|
if (uiState.isLoading) {
|
||||||
|
CardLoadingIndicator()
|
||||||
|
} else {
|
||||||
|
EntriesCard(uiState.itemsList) { list, value ->
|
||||||
|
viewModel.updateSelection(list, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +175,7 @@ private fun EntryTypeCard(type: String, onClick: () -> Unit, modifier: Modifier
|
|||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
private fun EntryPreview() {
|
private fun EntryPreview() {
|
||||||
val satItem = SatItem(45555, "SatName", emptyList(), true)
|
val satItem = SatItem(45555, "Very long Satellite name", true)
|
||||||
MainTheme { Entry(item = satItem, onSelected = { _, _ -> run {} }, modifier = Modifier) }
|
MainTheme { Entry(item = satItem, onSelected = { _, _ -> run {} }, modifier = Modifier) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,23 +212,15 @@ private fun Entry(item: SatItem, onSelected: (List<Int>, Boolean) -> Unit, modif
|
|||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
private fun EntriesPreview() {
|
private fun EntriesPreview() {
|
||||||
MainTheme { EntriesCard(DataState.Loading) { _, _ -> run {} } }
|
MainTheme { EntriesCard(emptyList()) { _, _ -> run {} } }
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun EntriesCard(state: DataState<List<SatItem>>, onSelected: (List<Int>, Boolean) -> Unit) {
|
fun EntriesCard(items: List<SatItem>, onSelected: (List<Int>, Boolean) -> Unit) {
|
||||||
ElevatedCard(modifier = Modifier.fillMaxSize()) {
|
LazyColumn {
|
||||||
when (state) {
|
items(items = items, key = { item -> item.catnum }) { entry ->
|
||||||
is DataState.Success -> {
|
Entry(entry, onSelected, Modifier.animateItemPlacement())
|
||||||
LazyColumn {
|
|
||||||
items(items = state.data, key = { item -> item.catnum }) { entry ->
|
|
||||||
Entry(entry, onSelected, Modifier.animateItemPlacement())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> CardLoadingIndicator()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.rtbishop.look4sat.presentation.entries
|
||||||
|
|
||||||
|
import com.rtbishop.look4sat.model.SatItem
|
||||||
|
|
||||||
|
data class EntriesScreenState(
|
||||||
|
val isLoading: Boolean,
|
||||||
|
val itemsList: List<SatItem>,
|
||||||
|
val currentType: String,
|
||||||
|
val typesList: List<String>,
|
||||||
|
)
|
||||||
@@ -17,115 +17,59 @@
|
|||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.presentation.entries
|
package com.rtbishop.look4sat.presentation.entries
|
||||||
|
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.lifecycle.viewmodel.initializer
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
import com.rtbishop.look4sat.MainApplication
|
import com.rtbishop.look4sat.MainApplication
|
||||||
import com.rtbishop.look4sat.domain.IDataRepository
|
import com.rtbishop.look4sat.data.SelectionRepository
|
||||||
import com.rtbishop.look4sat.domain.ISettingsRepository
|
|
||||||
import com.rtbishop.look4sat.model.DataState
|
|
||||||
import com.rtbishop.look4sat.model.SatItem
|
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.*
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
class EntriesViewModel(private val selectionRepo: SelectionRepository) : ViewModel() {
|
||||||
class EntriesViewModel(
|
|
||||||
private val dataRepository: IDataRepository,
|
|
||||||
private val settingsRepository: ISettingsRepository,
|
|
||||||
private val dispatcher: CoroutineDispatcher = Dispatchers.Default
|
|
||||||
) : ViewModel() {
|
|
||||||
|
|
||||||
private val satType = MutableStateFlow("All")
|
private val defaultUiState = EntriesScreenState(
|
||||||
private val currentQuery = MutableStateFlow(String())
|
isLoading = true,
|
||||||
private val itemsFromRepo = MutableStateFlow<List<SatItem>>(emptyList())
|
itemsList = emptyList(),
|
||||||
private val itemsWithType = satType.flatMapLatest { type ->
|
currentType = selectionRepo.getCurrentType(),
|
||||||
itemsFromRepo.map { items -> filterByType(items, type) }
|
typesList = selectionRepo.getTypesList()
|
||||||
}
|
)
|
||||||
private val itemsWithQuery = currentQuery.flatMapLatest { query ->
|
val uiState = mutableStateOf(defaultUiState)
|
||||||
itemsWithType.map { items -> filterByQuery(items, query) }
|
|
||||||
}
|
|
||||||
val satData = itemsWithQuery.map { items -> DataState.Success(items) }
|
|
||||||
val satTypes = dataRepository.getSatelliteTypes()
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
delay(250)
|
delay(1000)
|
||||||
itemsFromRepo.value = dataRepository.getEntriesWithSelection()
|
selectionRepo.getEntriesFlow().collect { items ->
|
||||||
|
uiState.value = uiState.value.copy(isLoading = false, itemsList = items)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSatType() = satType.value
|
fun setType(type: String) = viewModelScope.launch {
|
||||||
|
selectionRepo.setType(type)
|
||||||
fun setSatType(type: String) {
|
uiState.value = uiState.value.copy(currentType = type)
|
||||||
satType.value = type
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun selectCurrentItems(selectAll: Boolean) = viewModelScope.launch {
|
fun setQuery(query: String) = viewModelScope.launch { selectionRepo.setQuery(query) }
|
||||||
updateEntriesSelection(itemsWithQuery.first().map { item -> item.catnum }, selectAll)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setQuery(query: String) {
|
fun updateSelection(selectAll: Boolean) = viewModelScope.launch {
|
||||||
currentQuery.value = query
|
selectionRepo.updateSelection(selectAll)
|
||||||
}
|
|
||||||
|
|
||||||
fun saveSelection() = viewModelScope.launch {
|
|
||||||
val newSelection = itemsFromRepo.value.filter { it.isSelected }.map { it.catnum }
|
|
||||||
settingsRepository.saveEntriesSelection(newSelection)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateSelection(catNums: List<Int>, isSelected: Boolean) = viewModelScope.launch {
|
fun updateSelection(catNums: List<Int>, isSelected: Boolean) = viewModelScope.launch {
|
||||||
updateEntriesSelection(catNums, isSelected)
|
selectionRepo.updateSelection(catNums, isSelected)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
|
fun saveSelection() = viewModelScope.launch { selectionRepo.saveSelection() }
|
||||||
withContext(dispatcher) {
|
|
||||||
itemsFromRepo.value.let { itemsAll ->
|
|
||||||
val copiedList = itemsAll.map { item -> item.copy() }
|
|
||||||
catNums.forEach { catnum ->
|
|
||||||
copiedList.find { item -> item.catnum == catnum }?.isSelected = isSelected
|
|
||||||
}
|
|
||||||
itemsFromRepo.value = copiedList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun filterByType(items: List<SatItem>, type: String): List<SatItem> {
|
|
||||||
return withContext(dispatcher) {
|
|
||||||
if (type == "All") return@withContext items
|
|
||||||
val catnums = settingsRepository.loadSatType(type)
|
|
||||||
if (catnums.isEmpty()) return@withContext items
|
|
||||||
return@withContext items.filter { item -> item.catnum in catnums }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun filterByQuery(items: List<SatItem>, query: String): List<SatItem> {
|
|
||||||
return withContext(dispatcher) {
|
|
||||||
if (query.isBlank()) return@withContext items
|
|
||||||
return@withContext try {
|
|
||||||
items.filter { it.catnum == query.toInt() }
|
|
||||||
} catch (e: Exception) {
|
|
||||||
items.filter { item -> item.name.lowercase().contains(query.lowercase()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
val applicationKey = ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY
|
val applicationKey = ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY
|
||||||
initializer {
|
initializer {
|
||||||
val container = (this[applicationKey] as MainApplication).container
|
val container = (this[applicationKey] as MainApplication).container
|
||||||
EntriesViewModel(
|
EntriesViewModel(container.provideSelectionRepository())
|
||||||
container.dataRepository,
|
|
||||||
container.settingsRepository
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,15 +55,13 @@ class DataRepository(
|
|||||||
|
|
||||||
override fun getSatelliteTypes() = remoteSource.satelliteSourcesMap.keys.sorted()
|
override fun getSatelliteTypes() = remoteSource.satelliteSourcesMap.keys.sorted()
|
||||||
|
|
||||||
override suspend fun getEntriesWithModes() = entrySource.getEntriesWithModes()
|
override suspend fun getEntriesList(): List<SatItem> {
|
||||||
|
val selectedIds = settingsRepository.satelliteSelection.value
|
||||||
|
return entrySource.getEntriesList().map { it.copy(isSelected = it.catnum in selectedIds) }
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun getEntriesWithIds(ids: List<Int>) = entrySource.getEntriesWithIds(ids)
|
override suspend fun getEntriesWithIds(ids: List<Int>) = entrySource.getEntriesWithIds(ids)
|
||||||
|
|
||||||
override suspend fun getEntriesWithSelection(): List<SatItem> {
|
|
||||||
val selectedIds = settingsRepository.satelliteSelection.value
|
|
||||||
return getEntriesWithModes().onEach { it.isSelected = it.catnum in selectedIds }
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getRadiosWithId(id: Int) = radioSource.getRadiosWithId(id)
|
override suspend fun getRadiosWithId(id: Int) = radioSource.getRadiosWithId(id)
|
||||||
|
|
||||||
override fun updateFromFile(uri: String) {
|
override fun updateFromFile(uri: String) {
|
||||||
@@ -93,6 +91,7 @@ class DataRepository(
|
|||||||
settingsRepository.saveSatType(type, catnums)
|
settingsRepository.saveSatType(type, catnums)
|
||||||
importedEntries.addAll(satellites)
|
importedEntries.addAll(satellites)
|
||||||
}
|
}
|
||||||
|
|
||||||
"McCants", "Classified" -> {
|
"McCants", "Classified" -> {
|
||||||
// unzip and parse tle stream
|
// unzip and parse tle stream
|
||||||
val unzipped = ZipInputStream(stream).apply { nextEntry }
|
val unzipped = ZipInputStream(stream).apply { nextEntry }
|
||||||
@@ -101,6 +100,7 @@ class DataRepository(
|
|||||||
settingsRepository.saveSatType(type, catnums)
|
settingsRepository.saveSatType(type, catnums)
|
||||||
importedEntries.addAll(satellites)
|
importedEntries.addAll(satellites)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
// parse csv stream
|
// parse csv stream
|
||||||
val parsed = dataParser.parseCSVStream(stream)
|
val parsed = dataParser.parseCSVStream(stream)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ interface IEntriesStorage {
|
|||||||
|
|
||||||
fun getEntriesTotal(): Flow<Int>
|
fun getEntriesTotal(): Flow<Int>
|
||||||
|
|
||||||
suspend fun getEntriesWithModes(): List<SatItem>
|
suspend fun getEntriesList(): List<SatItem>
|
||||||
|
|
||||||
suspend fun getEntriesWithIds(ids: List<Int>): List<Satellite>
|
suspend fun getEntriesWithIds(ids: List<Int>): List<Satellite>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package com.rtbishop.look4sat.data
|
||||||
|
|
||||||
|
import com.rtbishop.look4sat.domain.IDataRepository
|
||||||
|
import com.rtbishop.look4sat.domain.ISettingsRepository
|
||||||
|
import com.rtbishop.look4sat.model.SatItem
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
class SelectionRepository(
|
||||||
|
private val dispatcher: CoroutineDispatcher,
|
||||||
|
private val dataRepository: IDataRepository,
|
||||||
|
private val settingsRepository: ISettingsRepository
|
||||||
|
) {
|
||||||
|
private val currentItems = MutableStateFlow<List<SatItem>>(emptyList())
|
||||||
|
private val currentType = MutableStateFlow("All")
|
||||||
|
private val currentQuery = MutableStateFlow("")
|
||||||
|
private val itemsWithType = currentType.flatMapLatest { type ->
|
||||||
|
currentItems.map { items -> items.filterByType(type) }
|
||||||
|
}
|
||||||
|
private val itemsWithQuery = currentQuery.flatMapLatest { query ->
|
||||||
|
itemsWithType.map { items -> items.filterByQuery(query) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCurrentType() = currentType.value
|
||||||
|
|
||||||
|
fun getTypesList() = dataRepository.getSatelliteTypes()
|
||||||
|
|
||||||
|
suspend fun getEntriesFlow() = withContext(dispatcher) {
|
||||||
|
currentItems.value = dataRepository.getEntriesList()
|
||||||
|
return@withContext itemsWithQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun setType(type: String) = withContext(dispatcher) { currentType.value = type }
|
||||||
|
|
||||||
|
suspend fun setQuery(query: String) = withContext(dispatcher) { currentQuery.value = query }
|
||||||
|
|
||||||
|
suspend fun updateSelection(selectAll: Boolean) = withContext(dispatcher) {
|
||||||
|
updateSelection(itemsWithQuery.first().map { item -> item.catnum }, selectAll)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun updateSelection(catNums: List<Int>, isSelected: Boolean) = withContext(dispatcher) {
|
||||||
|
currentItems.value = currentItems.value.map { item ->
|
||||||
|
if (item.catnum in catNums) item.copy(isSelected = isSelected) else item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun saveSelection() = withContext(dispatcher) {
|
||||||
|
val currentSelection = currentItems.value.filter { it.isSelected }.map { it.catnum }
|
||||||
|
settingsRepository.saveEntriesSelection(currentSelection)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun List<SatItem>.filterByType(type: String) = withContext(dispatcher) {
|
||||||
|
if (type == "All") return@withContext this@filterByType
|
||||||
|
val catnums = settingsRepository.loadSatType(type)
|
||||||
|
if (catnums.isEmpty()) return@withContext this@filterByType
|
||||||
|
return@withContext this@filterByType.filter { item -> item.catnum in catnums }
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun List<SatItem>.filterByQuery(query: String) = withContext(dispatcher) {
|
||||||
|
if (query.isBlank()) return@withContext this@filterByQuery
|
||||||
|
return@withContext try {
|
||||||
|
this@filterByQuery.filter { it.catnum == query.toInt() }
|
||||||
|
} catch (e: Exception) {
|
||||||
|
this@filterByQuery.filter { item -> item.name.lowercase().contains(query.lowercase()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,12 +33,10 @@ interface IDataRepository {
|
|||||||
|
|
||||||
fun getSatelliteTypes(): List<String>
|
fun getSatelliteTypes(): List<String>
|
||||||
|
|
||||||
suspend fun getEntriesWithModes(): List<SatItem>
|
suspend fun getEntriesList(): List<SatItem>
|
||||||
|
|
||||||
suspend fun getEntriesWithIds(ids: List<Int>): List<Satellite>
|
suspend fun getEntriesWithIds(ids: List<Int>): List<Satellite>
|
||||||
|
|
||||||
suspend fun getEntriesWithSelection(): List<SatItem>
|
|
||||||
|
|
||||||
suspend fun getRadiosWithId(id: Int): List<SatRadio>
|
suspend fun getRadiosWithId(id: Int): List<SatRadio>
|
||||||
|
|
||||||
fun updateFromFile(uri: String)
|
fun updateFromFile(uri: String)
|
||||||
|
|||||||
@@ -20,6 +20,6 @@ package com.rtbishop.look4sat.model
|
|||||||
data class SatItem(
|
data class SatItem(
|
||||||
val catnum: Int,
|
val catnum: Int,
|
||||||
val name: String,
|
val name: String,
|
||||||
val modes: List<String>,
|
// val modes: List<String>,
|
||||||
var isSelected: Boolean
|
val isSelected: Boolean
|
||||||
)
|
)
|
||||||
Reference in new issue
Block a user