mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Minor fixes for entries, settings and maps
This commit is contained in:
1 parent
942c7ce65f
commit
5d2a870319
10 files changed
+140
-125
No files matched your search
@@ -26,6 +26,7 @@ import com.rtbishop.look4sat.framework.data.remote.NetworkSource
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import org.osmdroid.config.Configuration
|
||||||
|
|
||||||
class MainContainer(private val context: Context) {
|
class MainContainer(private val context: Context) {
|
||||||
|
|
||||||
@@ -70,6 +71,7 @@ class MainContainer(private val context: Context) {
|
|||||||
private fun provideSettingsRepository(): ISettingsRepository {
|
private fun provideSettingsRepository(): ISettingsRepository {
|
||||||
val manager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
val manager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||||
val preferences = context.getSharedPreferences("default", Context.MODE_PRIVATE)
|
val preferences = context.getSharedPreferences("default", Context.MODE_PRIVATE)
|
||||||
|
Configuration.getInstance().load(context, preferences)
|
||||||
return SettingsRepository(manager, preferences)
|
return SettingsRepository(manager, preferences)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,15 +124,17 @@ class SettingsRepository(
|
|||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
override fun saveEntriesSelection(catnums: List<Int>) {
|
private val _satelliteSelection = MutableStateFlow(loadEntriesSelection())
|
||||||
val stringList = catnums.map { catnum -> catnum.toString() }
|
override val satelliteSelection: StateFlow<List<Int>> = _satelliteSelection
|
||||||
preferences.edit { putStringSet(keySelection, stringList.toSet()) }
|
|
||||||
|
override fun saveEntriesSelection(catnums: List<Int>) = preferences.edit {
|
||||||
|
putStringSet(keySelection, catnums.map { catnum -> catnum.toString() }.toSet())
|
||||||
|
_satelliteSelection.value = catnums
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadEntriesSelection(): List<Int> {
|
private fun loadEntriesSelection(): List<Int> {
|
||||||
val catnums =
|
val catNums = preferences.getStringSet(keySelection, emptySet())
|
||||||
preferences.getStringSet(keySelection, emptySet())?.map { catnum -> catnum.toInt() }
|
return catNums?.map { catnum -> catnum.toInt() }?.sorted() ?: emptyList()
|
||||||
return catnums?.sorted() ?: emptyList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveSatType(type: String, catnums: List<Int>) {
|
override fun saveSatType(type: String, catnums: List<Int>) {
|
||||||
|
|||||||
@@ -10,12 +10,19 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.ElevatedButton
|
||||||
|
import androidx.compose.material3.ElevatedCard
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.composed
|
import androidx.compose.ui.composed
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@@ -31,6 +38,16 @@ fun CardButton(onClick: () -> Unit, text: String, modifier: Modifier = Modifier)
|
|||||||
) { Text(text = text, fontSize = 17.sp) }
|
) { Text(text = text, fontSize = 17.sp) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CardIcon(onClick: () -> Unit, iconId: Int, description: String? = null) {
|
||||||
|
val clickableModifier = Modifier.clickable { onClick() }
|
||||||
|
ElevatedCard(modifier = Modifier.size(48.dp)) {
|
||||||
|
Box(modifier = clickableModifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Icon(painter = painterResource(id = iconId), contentDescription = description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CardLoadingIndicator() {
|
fun CardLoadingIndicator() {
|
||||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
|
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import androidx.compose.foundation.clickable
|
|||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
|
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.collectAsState
|
||||||
@@ -13,8 +14,10 @@ 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
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
@@ -25,6 +28,7 @@ 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.DataState
|
||||||
import com.rtbishop.look4sat.model.SatItem
|
import com.rtbishop.look4sat.model.SatItem
|
||||||
|
import com.rtbishop.look4sat.presentation.CardIcon
|
||||||
import com.rtbishop.look4sat.presentation.CardLoadingIndicator
|
import com.rtbishop.look4sat.presentation.CardLoadingIndicator
|
||||||
import com.rtbishop.look4sat.presentation.MainTheme
|
import com.rtbishop.look4sat.presentation.MainTheme
|
||||||
import com.rtbishop.look4sat.presentation.dialogs.TypesDialog
|
import com.rtbishop.look4sat.presentation.dialogs.TypesDialog
|
||||||
@@ -50,12 +54,7 @@ fun EntriesScreen(navToPasses: () -> Unit) {
|
|||||||
viewModel.saveSelection()
|
viewModel.saveSelection()
|
||||||
navToPasses()
|
navToPasses()
|
||||||
})
|
})
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.height(48.dp)) {
|
MiddleBar(viewModel.getSatType(), { toggleDialog() }, { unselectAll() }, { selectAll() })
|
||||||
EntryTypeCard(
|
|
||||||
type = viewModel.getSatType(), { toggleDialog() }, modifier = Modifier.weight(1f)
|
|
||||||
)
|
|
||||||
SelectionCard(unselectAll = { unselectAll() }, selectAll = { selectAll() })
|
|
||||||
}
|
|
||||||
EntriesCard(state = state.value) { list, value -> viewModel.updateSelection(list, value) }
|
EntriesCard(state = state.value) { list, value -> viewModel.updateSelection(list, value) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,83 +63,81 @@ fun EntriesScreen(navToPasses: () -> Unit) {
|
|||||||
@Composable
|
@Composable
|
||||||
private fun TopBarPreview() = MainTheme { TopBar({}, {}) }
|
private fun TopBarPreview() = MainTheme { TopBar({}, {}) }
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
@Composable
|
|
||||||
private fun MiddleBarPreview() = MainTheme { MiddleBar({}, {}) }
|
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
@Composable
|
|
||||||
private fun EntryPreview() {
|
|
||||||
val satItem = SatItem(45555, "SatName", emptyList(), true)
|
|
||||||
MainTheme { Entry(item = satItem, onSelected = { _, _ -> run {} }, modifier = Modifier) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
@Composable
|
|
||||||
private fun EntriesPreview() {
|
|
||||||
MainTheme { EntriesCard(DataState.Loading) { _, _ -> run {} } }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopBar(setQuery: (String) -> Unit, saveSelection: () -> Unit) {
|
private fun TopBar(setQuery: (String) -> Unit, saveSelection: () -> Unit) {
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.height(56.dp)) {
|
Row(horizontalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.height(48.dp)) {
|
||||||
SearchBar(setQuery = { setQuery(it) }, modifier = Modifier.weight(1f))
|
SearchBar(setQuery = { setQuery(it) }, modifier = Modifier.weight(1f))
|
||||||
SaveButton(saveSelection = { saveSelection() }, modifier = Modifier.height(56.dp))
|
SaveButton(saveSelection = { saveSelection() }, modifier = Modifier.height(48.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SearchBar(setQuery: (String) -> Unit, modifier: Modifier = Modifier) {
|
private fun SearchBar(setQuery: (String) -> Unit, modifier: Modifier = Modifier) {
|
||||||
val currentQuery = rememberSaveable { mutableStateOf("") }
|
val currentQuery = rememberSaveable { mutableStateOf("") }
|
||||||
OutlinedTextField(
|
val setNewQuery = { newValue: String ->
|
||||||
value = currentQuery.value,
|
|
||||||
onValueChange = { newValue ->
|
|
||||||
currentQuery.value = newValue
|
currentQuery.value = newValue
|
||||||
setQuery(newValue)
|
setQuery(newValue)
|
||||||
},
|
}
|
||||||
maxLines = 1,
|
ElevatedCard(modifier = modifier.height(48.dp)) {
|
||||||
// label = { Text(text = stringResource(id = R.string.entries_search_hint)) },
|
Row(
|
||||||
placeholder = { Text(text = stringResource(id = R.string.entries_search_hint)) },
|
horizontalArrangement = Arrangement.Start,
|
||||||
leadingIcon = {
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
Icon(
|
modifier = Modifier.padding(start = 12.dp)
|
||||||
painter = painterResource(id = R.drawable.ic_search),
|
) {
|
||||||
contentDescription = null
|
Icon(painter = painterResource(id = R.drawable.ic_search), contentDescription = null)
|
||||||
)
|
BasicTextField(
|
||||||
},
|
value = currentQuery.value,
|
||||||
trailingIcon = {
|
onValueChange = { setNewQuery(it) },
|
||||||
Icon(painter = painterResource(id = R.drawable.ic_close),
|
singleLine = true,
|
||||||
contentDescription = null,
|
modifier = modifier.padding(start = 12.dp),
|
||||||
modifier = Modifier.onClick {
|
textStyle = TextStyle(
|
||||||
currentQuery.value = ""
|
fontSize = 16.sp,
|
||||||
setQuery("")
|
fontWeight = FontWeight.Medium,
|
||||||
})
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
},
|
|
||||||
shape = MaterialTheme.shapes.medium,
|
|
||||||
colors = TextFieldDefaults.outlinedTextFieldColors(
|
|
||||||
containerColor = MaterialTheme.colorScheme.surface,
|
|
||||||
focusedBorderColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
unfocusedBorderColor = MaterialTheme.colorScheme.onSurfaceVariant
|
|
||||||
),
|
),
|
||||||
modifier = modifier
|
decorationBox = { innerTextField ->
|
||||||
|
if (currentQuery.value.isEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.entries_search_hint),
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
innerTextField()
|
||||||
|
},
|
||||||
|
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurface)
|
||||||
|
)
|
||||||
|
IconButton(onClick = { setNewQuery("") }) {
|
||||||
|
Icon(painter = painterResource(id = R.drawable.ic_close), contentDescription = null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SaveButton(saveSelection: () -> Unit, modifier: Modifier = Modifier) {
|
private fun SaveButton(saveSelection: () -> Unit, modifier: Modifier = Modifier) {
|
||||||
ElevatedButton(
|
val clickableModifier = modifier.clickable { saveSelection() }
|
||||||
onClick = { saveSelection() }, colors = ButtonDefaults.buttonColors(
|
ElevatedCard(
|
||||||
containerColor = MaterialTheme.colorScheme.primary,
|
modifier = Modifier.width(102.dp),
|
||||||
contentColor = MaterialTheme.colorScheme.onPrimary
|
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primary)
|
||||||
), shape = MaterialTheme.shapes.medium, modifier = modifier.width(96.dp)
|
) {
|
||||||
) { Icon(painter = painterResource(id = R.drawable.ic_checkmark), contentDescription = null) }
|
Box(modifier = clickableModifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Icon(painter = painterResource(id = R.drawable.ic_checkmark), contentDescription = null)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
private fun MiddleBar(unselectAll: () -> Unit, selectAll: () -> Unit) {
|
private fun MiddleBarPreview() = MainTheme { MiddleBar("Amateur", {}, {}, {}) }
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun MiddleBar(type: String, navigate: () -> Unit, uncheck: () -> Unit, check: () -> Unit) {
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.height(48.dp)) {
|
Row(horizontalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.height(48.dp)) {
|
||||||
EntryTypeCard(type = "Amateur", {}, modifier = Modifier.weight(1f))
|
EntryTypeCard(type = type, { navigate() }, modifier = Modifier.weight(1f))
|
||||||
SelectionCard(unselectAll = { unselectAll() }, selectAll = { selectAll() })
|
CardIcon(onClick = { uncheck() }, iconId = R.drawable.ic_checkbox_off)
|
||||||
|
CardIcon(onClick = { check() }, iconId = R.drawable.ic_checkbox_on)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,27 +160,17 @@ private fun EntryTypeCard(type: String, onClick: () -> Unit, modifier: Modifier
|
|||||||
text = "Type: $type",
|
text = "Type: $type",
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
modifier = modifier.padding(start = 16.dp, end = 6.dp, bottom = 2.dp)
|
modifier = modifier.padding(start = 12.dp, end = 6.dp, bottom = 2.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
private fun SelectionCard(unselectAll: () -> Unit, selectAll: () -> Unit) {
|
private fun EntryPreview() {
|
||||||
ElevatedCard {
|
val satItem = SatItem(45555, "SatName", emptyList(), true)
|
||||||
Row(modifier = Modifier.width(96.dp)) {
|
MainTheme { Entry(item = satItem, onSelected = { _, _ -> run {} }, modifier = Modifier) }
|
||||||
val unselectIcon = painterResource(id = R.drawable.ic_checkbox_off)
|
|
||||||
val selectIcon = painterResource(id = R.drawable.ic_checkbox_on)
|
|
||||||
val iconColor = MaterialTheme.colorScheme.onSurface
|
|
||||||
IconButton(onClick = { unselectAll() }) {
|
|
||||||
Icon(painter = unselectIcon, contentDescription = null, tint = iconColor)
|
|
||||||
}
|
|
||||||
IconButton(onClick = { selectAll() }) {
|
|
||||||
Icon(painter = selectIcon, contentDescription = null, tint = iconColor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -216,6 +203,12 @@ private fun Entry(item: SatItem, onSelected: (List<Int>, Boolean) -> Unit, modif
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun EntriesPreview() {
|
||||||
|
MainTheme { EntriesCard(DataState.Loading) { _, _ -> run {} } }
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun EntriesCard(state: DataState<List<SatItem>>, onSelected: (List<Int>, Boolean) -> Unit) {
|
fun EntriesCard(state: DataState<List<SatItem>>, onSelected: (List<Int>, Boolean) -> Unit) {
|
||||||
|
|||||||
@@ -24,21 +24,23 @@ 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.domain.IDataRepository
|
||||||
import com.rtbishop.look4sat.domain.ISatelliteRepository
|
|
||||||
import com.rtbishop.look4sat.domain.ISettingsRepository
|
import com.rtbishop.look4sat.domain.ISettingsRepository
|
||||||
import com.rtbishop.look4sat.model.DataState
|
import com.rtbishop.look4sat.model.DataState
|
||||||
import com.rtbishop.look4sat.model.SatItem
|
import com.rtbishop.look4sat.model.SatItem
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class EntriesViewModel(
|
class EntriesViewModel(
|
||||||
private val dataRepository: IDataRepository,
|
private val dataRepository: IDataRepository,
|
||||||
private val satelliteRepository: ISatelliteRepository,
|
private val settingsRepository: ISettingsRepository,
|
||||||
private val settingsRepository: ISettingsRepository
|
private val dispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val satType = MutableStateFlow("All")
|
private val satType = MutableStateFlow("All")
|
||||||
@@ -67,7 +69,7 @@ class EntriesViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun selectCurrentItems(selectAll: Boolean) = viewModelScope.launch {
|
fun selectCurrentItems(selectAll: Boolean) = viewModelScope.launch {
|
||||||
updateSelection(itemsWithQuery.first().map { item -> item.catnum }, selectAll)
|
updateEntriesSelection(itemsWithQuery.first().map { item -> item.catnum }, selectAll)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setQuery(query: String) {
|
fun setQuery(query: String) {
|
||||||
@@ -77,16 +79,14 @@ class EntriesViewModel(
|
|||||||
fun saveSelection() = viewModelScope.launch {
|
fun saveSelection() = viewModelScope.launch {
|
||||||
val newSelection = itemsFromRepo.value.filter { it.isSelected }.map { it.catnum }
|
val newSelection = itemsFromRepo.value.filter { it.isSelected }.map { it.catnum }
|
||||||
settingsRepository.saveEntriesSelection(newSelection)
|
settingsRepository.saveEntriesSelection(newSelection)
|
||||||
val selectedIds = settingsRepository.loadEntriesSelection()
|
|
||||||
val satellites = dataRepository.getEntriesWithIds(selectedIds)
|
|
||||||
val stationPos = settingsRepository.stationPosition.value
|
|
||||||
val timeRef = System.currentTimeMillis()
|
|
||||||
val hoursAhead = settingsRepository.getHoursAhead()
|
|
||||||
val minElev = settingsRepository.getMinElevation()
|
|
||||||
satelliteRepository.calculatePasses(satellites, stationPos, timeRef, hoursAhead, minElev)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateSelection(catNums: List<Int>, isSelected: Boolean) {
|
fun updateSelection(catNums: List<Int>, isSelected: Boolean) = viewModelScope.launch {
|
||||||
|
updateEntriesSelection(catNums, isSelected)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
|
||||||
|
withContext(dispatcher) {
|
||||||
itemsFromRepo.value.let { itemsAll ->
|
itemsFromRepo.value.let { itemsAll ->
|
||||||
val copiedList = itemsAll.map { item -> item.copy() }
|
val copiedList = itemsAll.map { item -> item.copy() }
|
||||||
catNums.forEach { catnum ->
|
catNums.forEach { catnum ->
|
||||||
@@ -95,22 +95,24 @@ class EntriesViewModel(
|
|||||||
itemsFromRepo.value = copiedList
|
itemsFromRepo.value = copiedList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun filterByType(items: List<SatItem>, type: String): List<SatItem> {
|
|
||||||
if (type == "All") return items
|
|
||||||
val catnums = settingsRepository.loadSatType(type)
|
|
||||||
if (catnums.isEmpty()) return items
|
|
||||||
return items.filter { item -> item.catnum in catnums }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun filterByQuery(items: List<SatItem>, query: String): List<SatItem> {
|
private suspend fun filterByType(items: List<SatItem>, type: String): List<SatItem> {
|
||||||
if (query.isBlank()) return items
|
return withContext(dispatcher) {
|
||||||
return try {
|
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() }
|
items.filter { it.catnum == query.toInt() }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
items.filter { item ->
|
items.filter { item -> item.name.lowercase().contains(query.lowercase()) }
|
||||||
val itemName = item.name.lowercase(Locale.getDefault())
|
|
||||||
itemName.contains(query.lowercase(Locale.getDefault()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +124,6 @@ class EntriesViewModel(
|
|||||||
val container = (this[applicationKey] as MainApplication).container
|
val container = (this[applicationKey] as MainApplication).container
|
||||||
EntriesViewModel(
|
EntriesViewModel(
|
||||||
container.dataRepository,
|
container.dataRepository,
|
||||||
container.satelliteRepository,
|
|
||||||
container.settingsRepository
|
container.settingsRepository
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.rtbishop.look4sat.presentation.map
|
package com.rtbishop.look4sat.presentation.map
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
@@ -32,7 +31,6 @@ import com.rtbishop.look4sat.R
|
|||||||
import com.rtbishop.look4sat.domain.Satellite
|
import com.rtbishop.look4sat.domain.Satellite
|
||||||
import com.rtbishop.look4sat.model.GeoPos
|
import com.rtbishop.look4sat.model.GeoPos
|
||||||
import com.rtbishop.look4sat.model.SatPos
|
import com.rtbishop.look4sat.model.SatPos
|
||||||
import org.osmdroid.config.Configuration
|
|
||||||
import org.osmdroid.tileprovider.tilesource.XYTileSource
|
import org.osmdroid.tileprovider.tilesource.XYTileSource
|
||||||
import org.osmdroid.util.GeoPoint
|
import org.osmdroid.util.GeoPoint
|
||||||
import org.osmdroid.views.CustomZoomButtonsController
|
import org.osmdroid.views.CustomZoomButtonsController
|
||||||
@@ -66,9 +64,6 @@ private val labelRect = Rect()
|
|||||||
@Composable
|
@Composable
|
||||||
fun MapScreen() {
|
fun MapScreen() {
|
||||||
val viewModel = viewModel(MapViewModel::class.java, factory = MapViewModel.Factory)
|
val viewModel = viewModel(MapViewModel::class.java, factory = MapViewModel.Factory)
|
||||||
val context = LocalContext.current
|
|
||||||
val preferences = context.getSharedPreferences("default", Context.MODE_PRIVATE)
|
|
||||||
Configuration.getInstance().load(context, preferences)
|
|
||||||
viewModel.selectDefaultSatellite(-1)
|
viewModel.selectDefaultSatellite(-1)
|
||||||
val stationPos = viewModel.stationPos.collectAsState(initial = null)
|
val stationPos = viewModel.stationPos.collectAsState(initial = null)
|
||||||
val positions = viewModel.positions.collectAsState(initial = null)
|
val positions = viewModel.positions.collectAsState(initial = null)
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class MapViewModel(
|
|||||||
|
|
||||||
fun selectDefaultSatellite(catnum: Int) {
|
fun selectDefaultSatellite(catnum: Int) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val selectedIds = settingsRepository.loadEntriesSelection()
|
val selectedIds = settingsRepository.satelliteSelection.value
|
||||||
dataRepository.getEntriesWithIds(selectedIds).also { satellites ->
|
dataRepository.getEntriesWithIds(selectedIds).also { satellites ->
|
||||||
if (satellites.isNotEmpty()) {
|
if (satellites.isNotEmpty()) {
|
||||||
allSatellites = satellites
|
allSatellites = satellites
|
||||||
|
|||||||
@@ -87,12 +87,14 @@ class PassesViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
viewModelScope.launch {
|
||||||
|
settingsRepository.satelliteSelection.collect { calculatePasses() }
|
||||||
|
}
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
dataRepository.updateState.collect { updateState ->
|
dataRepository.updateState.collect { updateState ->
|
||||||
if (updateState is DataState.Success) calculatePasses()
|
if (updateState is DataState.Success) calculatePasses()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
calculatePasses()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shouldUseUTC() = settingsRepository.isUtcEnabled()
|
fun shouldUseUTC() = settingsRepository.isUtcEnabled()
|
||||||
@@ -100,18 +102,17 @@ class PassesViewModel(
|
|||||||
fun calculatePasses(
|
fun calculatePasses(
|
||||||
hoursAhead: Int = 1,
|
hoursAhead: Int = 1,
|
||||||
minElevation: Double = settingsRepository.getMinElevation(),
|
minElevation: Double = settingsRepository.getMinElevation(),
|
||||||
timeRef: Long = System.currentTimeMillis(),
|
timeRef: Long = System.currentTimeMillis()
|
||||||
selection: List<Int>? = null
|
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
_passes.emit(DataState.Loading)
|
_passes.emit(DataState.Loading)
|
||||||
// _timerText.postValue(timerDefaultText)
|
// _timerText.postValue(timerDefaultText)
|
||||||
passesProcessing?.cancelAndJoin()
|
passesProcessing?.cancelAndJoin()
|
||||||
selection?.let { items -> settingsRepository.saveEntriesSelection(items) }
|
// selection?.let { items -> settingsRepository.saveEntriesSelection(items) }
|
||||||
settingsRepository.setHoursAhead(hoursAhead)
|
settingsRepository.setHoursAhead(hoursAhead)
|
||||||
settingsRepository.setMinElevation(minElevation)
|
settingsRepository.setMinElevation(minElevation)
|
||||||
val stationPos = settingsRepository.stationPosition.value
|
val stationPos = settingsRepository.stationPosition.value
|
||||||
val selectedIds = settingsRepository.loadEntriesSelection()
|
val selectedIds = settingsRepository.satelliteSelection.value
|
||||||
val satellites = dataRepository.getEntriesWithIds(selectedIds)
|
val satellites = dataRepository.getEntriesWithIds(selectedIds)
|
||||||
satelliteRepository.calculatePasses(
|
satelliteRepository.calculatePasses(
|
||||||
satellites, stationPos, timeRef, hoursAhead, minElevation
|
satellites, stationPos, timeRef, hoursAhead, minElevation
|
||||||
|
|||||||
@@ -22,9 +22,13 @@ import com.rtbishop.look4sat.domain.ISettingsRepository
|
|||||||
import com.rtbishop.look4sat.model.DataState
|
import com.rtbishop.look4sat.model.DataState
|
||||||
import com.rtbishop.look4sat.model.SatEntry
|
import com.rtbishop.look4sat.model.SatEntry
|
||||||
import com.rtbishop.look4sat.model.SatItem
|
import com.rtbishop.look4sat.model.SatItem
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
|
|
||||||
@@ -56,7 +60,7 @@ class DataRepository(
|
|||||||
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> {
|
override suspend fun getEntriesWithSelection(): List<SatItem> {
|
||||||
val selectedIds = settingsRepository.loadEntriesSelection()
|
val selectedIds = settingsRepository.satelliteSelection.value
|
||||||
return getEntriesWithModes().onEach { it.isSelected = it.catnum in selectedIds }
|
return getEntriesWithModes().onEach { it.isSelected = it.catnum in selectedIds }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ interface ISettingsRepository {
|
|||||||
|
|
||||||
val stationPosition: StateFlow<GeoPos>
|
val stationPosition: StateFlow<GeoPos>
|
||||||
|
|
||||||
|
val satelliteSelection: StateFlow<List<Int>>
|
||||||
|
|
||||||
fun setGpsPosition(): Boolean
|
fun setGpsPosition(): Boolean
|
||||||
|
|
||||||
fun setGeoPosition(latitude: Double, longitude: Double, altitude: Double = 0.0): Boolean
|
fun setGeoPosition(latitude: Double, longitude: Double, altitude: Double = 0.0): Boolean
|
||||||
@@ -64,8 +66,6 @@ interface ISettingsRepository {
|
|||||||
|
|
||||||
fun saveEntriesSelection(catnums: List<Int>)
|
fun saveEntriesSelection(catnums: List<Int>)
|
||||||
|
|
||||||
fun loadEntriesSelection(): List<Int>
|
|
||||||
|
|
||||||
fun saveSatType(type: String, catnums: List<Int>)
|
fun saveSatType(type: String, catnums: List<Int>)
|
||||||
|
|
||||||
fun loadSatType(type: String): List<Int>
|
fun loadSatType(type: String): List<Int>
|
||||||
|
|||||||
Reference in new issue
Block a user