From bffb4842b17b3a1cb205613ac3251cc94ca16521 Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Sun, 23 Feb 2025 09:24:05 +0000 Subject: [PATCH] Added Selection Warning and App Welcome Dialogs --- .../presentation/components/Common.kt | 36 ++++++++++++++++--- .../presentation/passes/PassesScreen.kt | 9 +++++ .../presentation/passes/PassesState.kt | 2 ++ .../presentation/passes/PassesViewModel.kt | 10 +++++- .../presentation/radar/RadarScreen.kt | 3 +- .../satellites/SatellitesScreen.kt | 9 +++++ .../satellites/SatellitesState.kt | 2 ++ .../satellites/SatellitesViewModel.kt | 21 ++++++++--- .../presentation/settings/SettingsScreen.kt | 4 ++- app/src/main/res/values/strings.xml | 12 +++++++ .../look4sat/data/repository/SettingsRepo.kt | 27 ++++++++++---- .../look4sat/domain/model/Settings.kt | 4 ++- .../domain/repository/ISettingsRepo.kt | 2 ++ 13 files changed, 122 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/components/Common.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/components/Common.kt index 628938ae..34025f91 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/components/Common.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/components/Common.kt @@ -229,7 +229,7 @@ fun gotoUrl(context: Context, url: String) { } fun getDefaultPass(): OrbitalPass { - val orbitalData = OrbitalData("Next Satellite", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0.0) + val orbitalData = OrbitalData("No Future Passes", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0.0) val satellite = NearEarthObject(orbitalData) return OrbitalPass(0L, 0.0, 0L, 0.0, 0, 0.0, satellite, 0f) } @@ -248,6 +248,7 @@ fun SharedDialog( Text( text = title, fontSize = 18.sp, + fontWeight = FontWeight.Medium, color = MaterialTheme.colorScheme.primary, modifier = Modifier.padding(start = padding, top = padding, end = padding) ) @@ -262,6 +263,33 @@ fun SharedDialog( } } -//fun Modifier.onClick(onClick: () -> Unit): Modifier = composed { -// clickable(remember { MutableInteractionSource() }, null) { onClick() } -//} +@Composable +fun InfoDialog(title: String, text: String, onDismiss: () -> Unit) { + val padding = LocalSpacing.current.extraLarge + Dialog(onDismissRequest = onDismiss) { + ElevatedCard { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(padding) + ) { + Text( + text = title, + fontSize = 18.sp, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colorScheme.primary, + modifier = Modifier.padding(start = padding, top = padding, end = padding) + ) + Text( + text = text, + fontSize = 16.sp, + color = MaterialTheme.colorScheme.onSurface, + modifier = Modifier.padding(horizontal = padding) + ) + Row(modifier = Modifier.padding(start = padding, bottom = padding, end = padding)) { + Spacer(modifier = Modifier.weight(1f)) + CardButton(onClick = onDismiss, text = stringResource(id = R.string.btn_understand)) + } + } + } + } +} diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt index 5174d26f..e3936033 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt @@ -45,6 +45,7 @@ import com.rtbishop.look4sat.domain.predict.OrbitalPass import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.Screen import com.rtbishop.look4sat.presentation.components.CardIcon +import com.rtbishop.look4sat.presentation.components.InfoDialog import com.rtbishop.look4sat.presentation.components.NextPassRow import com.rtbishop.look4sat.presentation.components.TimerBar import com.rtbishop.look4sat.presentation.components.TimerRow @@ -81,6 +82,14 @@ private fun PassesScreen(uiState: PassesState, navigateToRadar: (Int, Long) -> U uiState.takeAction(PassesAction.FilterRadios(modes)) } } + if (uiState.shouldSeeWelcome) { + InfoDialog( + stringResource(R.string.passes_welcome_title), + stringResource(R.string.passes_welcome_message) + ) { + uiState.takeAction(PassesAction.DismissWelcome) + } + } Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { TimerRow { CardIcon(onClick = { showPassesDialog() }, iconId = R.drawable.ic_filter) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesState.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesState.kt index 2ba70937..24d6a43d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesState.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesState.kt @@ -14,10 +14,12 @@ data class PassesState( val elevation: Double, val modes: List, val itemsList: List, + val shouldSeeWelcome: Boolean, val takeAction: (PassesAction) -> Unit ) sealed class PassesAction { + data object DismissWelcome : PassesAction() data class FilterPasses(val hoursAhead: Int, val minElevation: Double) : PassesAction() data class FilterRadios(val modes: List) : PassesAction() data object RefreshPasses : PassesAction() diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt index 5f5f39d2..08f6062c 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt @@ -34,6 +34,7 @@ import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.update import kotlinx.coroutines.isActive import kotlinx.coroutines.launch @@ -55,6 +56,7 @@ class PassesViewModel( elevation = settingsRepo.passesSettings.value.minElevation, modes = settingsRepo.passesSettings.value.selectedModes, itemsList = emptyList(), + shouldSeeWelcome = settingsRepo.otherSettings.value.shouldSeeWelcome, takeAction = ::handleAction ) ) @@ -63,7 +65,7 @@ class PassesViewModel( init { viewModelScope.launch { - satelliteRepo.passes.collect { passes -> + satelliteRepo.passes.collectLatest { passes -> processing?.cancelAndJoin() processing = viewModelScope.launch { while (isActive) { @@ -76,10 +78,16 @@ class PassesViewModel( } } } + viewModelScope.launch { + settingsRepo.otherSettings.collectLatest { settings -> + _uiState.update { it.copy(shouldSeeWelcome = settings.shouldSeeWelcome) } + } + } } private fun handleAction(action: PassesAction) { when (action) { + PassesAction.DismissWelcome -> settingsRepo.setWelcomeDismissed() is PassesAction.FilterPasses -> applyFilter(action.hoursAhead, action.minElevation, uiState.value.modes) is PassesAction.FilterRadios -> applyFilter(uiState.value.hours, uiState.value.elevation, action.modes) PassesAction.RefreshPasses -> refreshPasses() diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt index 5a9f00af..66f6efba 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt @@ -159,7 +159,8 @@ private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) { Text( text = "This satellite doesn't have any known transcievers...", textAlign = TextAlign.Center, - fontSize = 18.sp + fontSize = 18.sp, + modifier = Modifier.padding(16.dp) ) } } else { diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesScreen.kt index 8682dc96..e44b635d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesScreen.kt @@ -48,6 +48,7 @@ import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.Screen import com.rtbishop.look4sat.presentation.components.CardIcon import com.rtbishop.look4sat.presentation.components.CardLoadingIndicator +import com.rtbishop.look4sat.presentation.components.InfoDialog fun NavGraphBuilder.satellitesDestination(navigateToPasses: () -> Unit) { composable(Screen.Satellites.route) { @@ -68,6 +69,14 @@ private fun SatellitesScreen(uiState: SatellitesState, navigateToPasses: () -> U uiState.takeAction(SatellitesAction.SelectTypes(it)) } } + if (uiState.shouldSeeWarning) { + InfoDialog( + stringResource(R.string.satellites_warning_title), + stringResource(R.string.satellites_warning_message) + ) { + uiState.takeAction(SatellitesAction.DismissWarning) + } + } val unselectAll = { uiState.takeAction(SatellitesAction.UnselectAll) } val selectAll = { uiState.takeAction(SatellitesAction.SelectAll) } Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesState.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesState.kt index f43b1ac1..598b14c8 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesState.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesState.kt @@ -5,6 +5,7 @@ import com.rtbishop.look4sat.domain.model.SatItem data class SatellitesState( val isDialogShown: Boolean, val isLoading: Boolean, + val shouldSeeWarning: Boolean, val itemsList: List, val currentTypes: List, val typesList: List, @@ -12,6 +13,7 @@ data class SatellitesState( ) sealed class SatellitesAction { + data object DismissWarning : SatellitesAction() data object SaveSelection : SatellitesAction() data class SearchFor(val query: String) : SatellitesAction() data object SelectAll : SatellitesAction() diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesViewModel.kt index b4865b86..2a0ea3c7 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satellites/SatellitesViewModel.kt @@ -24,18 +24,25 @@ import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory import com.rtbishop.look4sat.MainApplication import com.rtbishop.look4sat.domain.repository.ISelectionRepo +import com.rtbishop.look4sat.domain.repository.ISettingsRepo import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -class SatellitesViewModel(private val selectionRepo: ISelectionRepo) : ViewModel() { +class SatellitesViewModel( + private val selectionRepo: ISelectionRepo, + private val settingsRepo: ISettingsRepo +) : ViewModel() { private val defaultTypes = selectionRepo.getCurrentTypes() private val _uiState = MutableStateFlow( SatellitesState( isDialogShown = false, isLoading = true, + shouldSeeWarning = settingsRepo.otherSettings.value.shouldSeeWarning, itemsList = emptyList(), currentTypes = defaultTypes, typesList = selectionRepo.getTypesList(), @@ -48,14 +55,20 @@ class SatellitesViewModel(private val selectionRepo: ISelectionRepo) : ViewModel viewModelScope.launch { delay(1000) selectionRepo.setTypes(defaultTypes) - selectionRepo.getEntriesFlow().collect { items -> - _uiState.value = _uiState.value.copy(isLoading = false, itemsList = items) + selectionRepo.getEntriesFlow().collectLatest { items -> + _uiState.update { it.copy(isLoading = false, itemsList = items) } + } + } + viewModelScope.launch { + settingsRepo.otherSettings.collectLatest { settings -> + _uiState.update { it.copy(shouldSeeWarning = settings.shouldSeeWarning) } } } } private fun handleAction(action: SatellitesAction) { when (action) { + SatellitesAction.DismissWarning -> settingsRepo.setWarningDismissed() SatellitesAction.SaveSelection -> saveSelection() is SatellitesAction.SearchFor -> searchFor(action.query) SatellitesAction.SelectAll -> selectAll(true) @@ -93,7 +106,7 @@ class SatellitesViewModel(private val selectionRepo: ISelectionRepo) : ViewModel val applicationKey = ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY initializer { val container = (this[applicationKey] as MainApplication).container - SatellitesViewModel(container.selectionRepo) + SatellitesViewModel(container.selectionRepo, container.settingsRepo) } } } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt index 78002649..edf5fa31 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt @@ -406,7 +406,9 @@ private fun OtherCardPreview() = MainTheme { stateOfSensors = true, stateOfSweep = true, stateOfUtc = false, - stateOfLightTheme = false + stateOfLightTheme = false, + shouldSeeWarning = false, + shouldSeeWelcome = false ) OtherCard(settings = values, {}, {}, {}, {}, {}) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1946235c..2213e48a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,6 +15,7 @@ Add Accept + I Understand Cancel Back Modes @@ -43,6 +44,17 @@ + Warning\! + + There are over 9000 satellites listed in this app. + It makes no sense to track them all at the same time. + \n\nAlways try to narrow down the list to only the ones + you\'re interested in via search and types selector. + Welcome to Look4Sat\! + + Make sure to set your position via GPS, Lat/Lon or QTH in Settings. + \n\nPlease update the database at least weekly to get accurate predictions. + Filter passes Hours ahead Show passes that occur within X hours diff --git a/data/src/main/java/com/rtbishop/look4sat/data/repository/SettingsRepo.kt b/data/src/main/java/com/rtbishop/look4sat/data/repository/SettingsRepo.kt index 0dd599b8..a634a88b 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/repository/SettingsRepo.kt +++ b/data/src/main/java/com/rtbishop/look4sat/data/repository/SettingsRepo.kt @@ -61,6 +61,8 @@ class SettingsRepo(private val manager: LocationManager, private val preferences private val keyStationQth = "stationQth" private val keyStationTimestamp = "stationTimestamp" private val keyUpdateTimestamp = "updateTimestamp" + private val keyShouldSeeWarning = "shouldSeeWarning" + private val keyShouldSeeWelcome = "shouldSeeWelcome" private val separatorComma = "," //region # Satellites selection settings @@ -250,14 +252,25 @@ class SettingsRepo(private val manager: LocationManager, private val preferences _otherSettings.value = otherSettings.value.copy(stateOfLightTheme = value) } - private fun getOtherSettings(): OtherSettings { - val stateOfAutoUpdate = preferences.getBoolean(keyStateOfAutoUpdate, true) - val stateOfSensors = preferences.getBoolean(keyStateOfSensors, true) - val stateOfSweep = preferences.getBoolean(keyStateOfSweep, true) - val stateOfUtc = preferences.getBoolean(keyStateOfUtc, false) - val stateOfLightTheme = preferences.getBoolean(keyStateOfLightTheme,false) - return OtherSettings(stateOfAutoUpdate, stateOfSensors, stateOfSweep, stateOfUtc, stateOfLightTheme) + override fun setWarningDismissed() { + preferences.edit { putBoolean(keyShouldSeeWarning, false) } + _otherSettings.value = otherSettings.value.copy(shouldSeeWarning = false) } + + override fun setWelcomeDismissed() { + preferences.edit { putBoolean(keyShouldSeeWelcome, false) } + _otherSettings.value = otherSettings.value.copy(shouldSeeWelcome = false) + } + + private fun getOtherSettings(): OtherSettings = OtherSettings( + stateOfAutoUpdate = preferences.getBoolean(keyStateOfAutoUpdate, true), + stateOfSensors = preferences.getBoolean(keyStateOfSensors, true), + stateOfSweep = preferences.getBoolean(keyStateOfSweep, true), + stateOfUtc = preferences.getBoolean(keyStateOfUtc, false), + stateOfLightTheme = preferences.getBoolean(keyStateOfLightTheme, false), + shouldSeeWarning = preferences.getBoolean(keyShouldSeeWarning, true), + shouldSeeWelcome = preferences.getBoolean(keyShouldSeeWelcome, true) + ) //endregion //region # Undefined settings diff --git a/domain/src/main/java/com/rtbishop/look4sat/domain/model/Settings.kt b/domain/src/main/java/com/rtbishop/look4sat/domain/model/Settings.kt index 8455e840..9eddfa60 100644 --- a/domain/src/main/java/com/rtbishop/look4sat/domain/model/Settings.kt +++ b/domain/src/main/java/com/rtbishop/look4sat/domain/model/Settings.kt @@ -17,5 +17,7 @@ data class OtherSettings( val stateOfSensors: Boolean, val stateOfSweep: Boolean, val stateOfUtc: Boolean, - val stateOfLightTheme: Boolean + val stateOfLightTheme: Boolean, + val shouldSeeWarning: Boolean, + val shouldSeeWelcome: Boolean ) diff --git a/domain/src/main/java/com/rtbishop/look4sat/domain/repository/ISettingsRepo.kt b/domain/src/main/java/com/rtbishop/look4sat/domain/repository/ISettingsRepo.kt index a332bd50..ebdd6d99 100644 --- a/domain/src/main/java/com/rtbishop/look4sat/domain/repository/ISettingsRepo.kt +++ b/domain/src/main/java/com/rtbishop/look4sat/domain/repository/ISettingsRepo.kt @@ -58,6 +58,8 @@ interface ISettingsRepo { fun setStateOfSweep(value: Boolean) fun setStateOfUtc(value: Boolean) fun setStateOfLightTheme(value: Boolean) + fun setWarningDismissed() + fun setWelcomeDismissed() //endregion //region # Undefined settings