diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/common/Components.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/common/Components.kt index fd1905f2..55e10f93 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/common/Components.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/common/Components.kt @@ -33,6 +33,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -216,10 +217,24 @@ fun CardLoadingIndicator() { } } +@Composable +fun EmptyListCard(message: String) { + Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.padding(32.dp) + ) { + Text(text = stringResource(R.string.empty_list_title), fontSize = 21.sp) + Text(text = message, fontSize = 18.sp, textAlign = TextAlign.Center) + } + } +} + fun getDefaultPass(): OrbitalPass { - val orbitalData = OrbitalData("No Future Passes", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0.0) + val orbitalData = OrbitalData("||=<☉>=||", 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) + return OrbitalPass(0L, 0.0, Long.MAX_VALUE, 0.0, 0, 0.0, satellite, 0f) } @Composable 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 a605e51d..4536feca 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.OrbitalData import com.rtbishop.look4sat.domain.predict.OrbitalPass import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.Screen +import com.rtbishop.look4sat.presentation.common.EmptyListCard import com.rtbishop.look4sat.presentation.common.IconCard import com.rtbishop.look4sat.presentation.common.InfoDialog import com.rtbishop.look4sat.presentation.common.NextPassRow @@ -139,17 +140,21 @@ private fun PassesList( ) } ) { - LazyVerticalGrid( - columns = GridCells.Adaptive(320.dp), - modifier = Modifier.fillMaxSize() - ) { - items(items = passes, key = { item -> item.catNum + item.aosTime }) { pass -> - NearEarthPass( - pass = pass, - navigateToRadar = navigateToRadar, - modifier = Modifier.animateItem(), - isVerticalLayout = isVerticalLayout - ) + if (passes.isEmpty()) { + EmptyListCard(message = stringResource(R.string.passes_empty_list_message)) + } else { + LazyVerticalGrid( + columns = GridCells.Adaptive(320.dp), + modifier = Modifier.fillMaxSize() + ) { + items(items = passes, key = { item -> item.catNum + item.aosTime }) { pass -> + NearEarthPass( + pass = pass, + navigateToRadar = navigateToRadar, + modifier = Modifier.animateItem(), + isVerticalLayout = isVerticalLayout + ) + } } } } 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 c86958f4..a0c75d11 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 @@ -65,6 +65,7 @@ class PassesViewModel( init { viewModelScope.launch { + delay(1000) satelliteRepo.passes.collectLatest { passes -> processing?.cancelAndJoin() processing = viewModelScope.launch { @@ -117,7 +118,7 @@ class PassesViewModel( val nextPass = passes.first { it.aosTime.minus(timeNow) > 0 } val time = nextPass.aosTime.minus(timeNow).toTimerString() _uiState.update { it.copy(nextPass = nextPass, nextTime = time, isNextTimeAos = true) } - } catch (exception: NoSuchElementException) { + } catch (_: NoSuchElementException) { val lastPass = passes.last() val time = lastPass.losTime.minus(timeNow).toTimerString() _uiState.update { it.copy(nextPass = lastPass, nextTime = time, isNextTimeAos = false) } 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 6b564659..ed012fd7 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 @@ -100,6 +100,9 @@ private fun RadarScreen(uiState: RadarState, navigateUp: () -> Unit) { if(isVerticalLayout()) { ElevatedCard(modifier = Modifier.weight(1f)) { Box(contentAlignment = Alignment.Center) { + if (uiState.orbitalPos == null) { + ElevatedCard(modifier = Modifier.fillMaxSize()) {} + } uiState.orbitalPos?.let { position -> RadarViewCompose( item = position, @@ -182,6 +185,9 @@ private fun RadarScreen(uiState: RadarState, navigateUp: () -> Unit) { Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) { ElevatedCard(modifier = Modifier.weight(1f)) { Box(contentAlignment = Alignment.Center) { + if (uiState.orbitalPos == null) { + ElevatedCard(modifier = Modifier.fillMaxSize()) {} + } uiState.orbitalPos?.let { position -> RadarViewCompose( item = position, @@ -355,7 +361,7 @@ private fun TransmitterItem(radio: SatRadio) { // BluetoothCIV.updateOnce(radio) // } // }) - ) { + ) { Surface(modifier = Modifier.padding(bottom = 2.dp)) { Column( verticalArrangement = Arrangement.spacedBy(4.dp), @@ -436,7 +442,7 @@ private fun FrequencyText(frequency: Long?) { Text( text = freqText, textAlign = TextAlign.Center, - fontSize = 21.sp, + fontSize = 18.sp, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary ) 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 c512f9dc..48532a3a 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 @@ -46,6 +46,7 @@ import com.rtbishop.look4sat.domain.model.SatItem import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.Screen import com.rtbishop.look4sat.presentation.common.CardLoadingIndicator +import com.rtbishop.look4sat.presentation.common.EmptyListCard import com.rtbishop.look4sat.presentation.common.IconCard import com.rtbishop.look4sat.presentation.common.InfoDialog import com.rtbishop.look4sat.presentation.common.TopBar @@ -104,10 +105,11 @@ private fun SatellitesScreen(uiState: SatellitesState, navigateUp: () -> Unit) { } } ElevatedCard(modifier = Modifier.fillMaxSize()) { - if (uiState.isLoading) { - CardLoadingIndicator() - } else { - SatellitesCard(uiState.itemsList) { id, isTicked -> + val emptyMessage = stringResource(R.string.satellites_empty_list_message) + when { + uiState.isLoading -> CardLoadingIndicator() + uiState.itemsList.isEmpty() -> EmptyListCard(message = emptyMessage) + else -> SatellitesCard(uiState.itemsList) { id, isTicked -> uiState.takeAction(SatellitesAction.SelectSingle(id, isTicked)) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dd1abf7d..a8d7faef 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,7 +12,6 @@ About - Add Accept I Understand @@ -42,14 +41,20 @@ GPLv3 Licence Privacy Policy - + + No items to display + + + Make sure your search query is correct and the DB is updated 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. + + Make sure your filters are correct and you have selected satellites Welcome to Look4Sat\! Make sure to set your position via GPS, Lat/Lon or QTH in Settings. @@ -80,7 +85,6 @@ Selected type: %s - Name / Id There are no upcoming satellite passes to display @@ -142,7 +146,6 @@ Wikimedia maps | Map data © OpenStreetMap contributors - Station position Latitude: %.4f° Longitude: %.4f° diff --git a/domain/src/main/java/com/rtbishop/look4sat/domain/utility/QthConverter.kt b/domain/src/main/java/com/rtbishop/look4sat/domain/utility/QthConverter.kt index 85b38e06..28459687 100644 --- a/domain/src/main/java/com/rtbishop/look4sat/domain/utility/QthConverter.kt +++ b/domain/src/main/java/com/rtbishop/look4sat/domain/utility/QthConverter.kt @@ -35,17 +35,14 @@ fun qthToPosition(locator: String): GeoPos? { fun positionToQth(latitude: Double, longitude: Double): String? { if (!isValidPosition(latitude, longitude)) return null - val tempLon = if (longitude > 180.0) longitude - 180 else longitude - val upper = "ABCDEFGHIJKLMNOPQRSTUVWX" - val lower = "abcdefghijklmnopqrstuvwx" - val newLongitude = tempLon + 180 + val newLongitude = if (longitude > 180.0) longitude else longitude + 180 val newLatitude = latitude + 90 - val lonFirst = upper[(newLongitude / 20).toInt()] - val latFirst = upper[(newLatitude / 10).toInt()] - val lonSecond = ((newLongitude / 2) % 10).toInt().toString() - val latSecond = (newLatitude % 10).toInt().toString() - val lonThird = lower[((newLongitude % 2) * 12).toInt()] - val latThird = lower[((newLatitude % 1) * 24).toInt()] + val lonFirst = (65 + (newLongitude / 20)).toInt().toChar() + val latFirst = (65 + (newLatitude / 10)).toInt().toChar() + val lonSecond = ((newLongitude / 2) % 10).toInt() + val latSecond = (newLatitude % 10).toInt() + val lonThird = (65 + (newLongitude % 2) * 12).toInt().toChar().lowercaseChar() + val latThird = (65 + (newLatitude % 1) * 24).toInt().toChar().lowercaseChar() return "$lonFirst$latFirst$lonSecond$latSecond$lonThird$latThird" } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 512ec21f..4da97ec0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,13 +1,13 @@ [versions] -android-gradle-plugin = "8.12.0" -google-ksp = "2.2.0-2.0.2" -kotlin = "2.2.0" +android-gradle-plugin = "8.12.1" +google-ksp = "2.2.10-2.0.2" +kotlin = "2.2.10" -androidx-core-ktx = "1.16.0" +androidx-core-ktx = "1.17.0" androidx-core-splashscreen = "1.0.1" androidx-room = "2.7.2" -compose-bom = "2025.07.00" +compose-bom = "2025.08.00" compose-activity = "1.10.1" compose-lifecycle = "2.9.2" compose-navigation = "2.9.3"