mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Implemented a basic map data card on MapScreen
This commit is contained in:
1 parent
880fe10bfd
commit
fdbdc513f1
12 files changed
+102
-65
No files matched your search
@@ -14,11 +14,10 @@ android {
|
||||
compileSdk = 35
|
||||
defaultConfig {
|
||||
applicationId = "com.rtbishop.look4sat"
|
||||
minSdk = 26
|
||||
minSdk = 24
|
||||
targetSdk = 35
|
||||
versionCode = 314
|
||||
versionName = "3.1.4"
|
||||
resourceConfigurations.addAll(listOf("en", "ru", "si", "zh-rCN", "anydpi"))
|
||||
versionCode = 400
|
||||
versionName = "4.0.0"
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildFeatures {
|
||||
|
||||
Vendored
-14
@@ -1,14 +0,0 @@
|
||||
# JSR 305 annotations are for embedding nullability information.
|
||||
-dontwarn javax.annotation.**
|
||||
|
||||
# A resource is loaded with a relative path so the package of this class must be preserved.
|
||||
-adaptresourcefilenames okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz
|
||||
|
||||
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
|
||||
-dontwarn org.codehaus.mojo.animal_sniffer.*
|
||||
|
||||
# OkHttp platform used only on JVM and when Conscrypt and other security providers are available.
|
||||
-dontwarn okhttp3.internal.platform.**
|
||||
-dontwarn org.conscrypt.**
|
||||
-dontwarn org.bouncycastle.**
|
||||
-dontwarn org.openjsse.**
|
||||
@@ -10,18 +10,26 @@ import android.graphics.Rect
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
@@ -86,6 +94,7 @@ private fun MapScreen(uiState: State<MapState>) {
|
||||
val rotateMod = Modifier.rotate(180f)
|
||||
val timeString = uiState.value.mapData?.aosTime ?: "00:00:00"
|
||||
val isTimeAos = uiState.value.mapData?.isTimeAos ?: true
|
||||
val osmInfo = "Wikimedia maps | Map data © OpenStreetMap contributors"
|
||||
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
TimerRow {
|
||||
CardIcon(onClick = selectPrev, iconId = R.drawable.ic_arrow, modifier = rotateMod)
|
||||
@@ -93,14 +102,48 @@ private fun MapScreen(uiState: State<MapState>) {
|
||||
CardIcon(onClick = selectNext, iconId = R.drawable.ic_arrow)
|
||||
}
|
||||
NextPassRow(pass = uiState.value.orbitalPass)
|
||||
ElevatedCard(modifier = Modifier.fillMaxSize()) {
|
||||
MapView(modifier = Modifier.fillMaxSize(), isLightUi = uiState.value.isLightUi) { mapView ->
|
||||
uiState.value.stationPosition?.let { setStationPosition(it, mapView) }
|
||||
uiState.value.positions?.let { setPositions(it, mapView, onItemClick) }
|
||||
uiState.value.track?.let { setSatelliteTrack(it, mapView) }
|
||||
uiState.value.footprint?.let { setFootprint(it, mapView) }
|
||||
ElevatedCard(modifier = Modifier.weight(1f)) {
|
||||
Box(contentAlignment = Alignment.BottomCenter) {
|
||||
MapView(isLightUi = uiState.value.isLightUi) { mapView ->
|
||||
uiState.value.stationPosition?.let { setStationPosition(it, mapView) }
|
||||
uiState.value.positions?.let { setPositions(it, mapView, onItemClick) }
|
||||
uiState.value.track?.let { setSatelliteTrack(it, mapView) }
|
||||
uiState.value.footprint?.let { setFootprint(it, mapView) }
|
||||
}
|
||||
Text(text = osmInfo, textAlign = TextAlign.Center, fontSize = 14.sp)
|
||||
}
|
||||
}
|
||||
uiState.value.mapData?.let { mapData ->
|
||||
ElevatedCard {
|
||||
MapDataCard(mapData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MapDataCard(mapData: MapData) {
|
||||
Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)) {
|
||||
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
|
||||
Text(text = stringResource(R.string.map_period, mapData.period), color = MaterialTheme.colorScheme.primary)
|
||||
Text(text = stringResource(R.string.map_phase, mapData.phase), color = MaterialTheme.colorScheme.primary)
|
||||
}
|
||||
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
|
||||
Text(text = stringResource(R.string.map_azimuth, mapData.azimuth))
|
||||
Text(text = stringResource(R.string.map_elevation, mapData.elevation))
|
||||
}
|
||||
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
|
||||
Text(text = stringResource(R.string.map_altitude, mapData.altitude), color = MaterialTheme.colorScheme.primary)
|
||||
Text(text = stringResource(R.string.map_distance, mapData.range), color = MaterialTheme.colorScheme.primary)
|
||||
}
|
||||
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
|
||||
Text(text = stringResource(R.string.map_latitude, mapData.osmPos.latitude))
|
||||
Text(text = stringResource(R.string.map_longitude, mapData.osmPos.longitude))
|
||||
}
|
||||
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
|
||||
Text(text = stringResource(R.string.map_qth, mapData.qthLoc), color = MaterialTheme.colorScheme.primary)
|
||||
Text(text = stringResource(R.string.map_velocity, mapData.velocity), color = MaterialTheme.colorScheme.primary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,30 +238,6 @@ private fun setFootprint(orbitalPos: OrbitalPos, mapView: MapView) {
|
||||
}
|
||||
}
|
||||
|
||||
//private fun handleMapData(mapData: MapData) {
|
||||
// binding.apply {
|
||||
// mapTimer.text = mapData.aosTime
|
||||
// mapDataPeriod.text = String.format(getString(R.string.map_period, mapData.period))
|
||||
// mapDataPhase.text = String.format(getString(R.string.map_phase), mapData.phase)
|
||||
// mapAzimuth.text = String.format(getString(R.string.map_azimuth), mapData.azimuth)
|
||||
// mapElevation.text = String.format(getString(R.string.map_elevation), mapData.elevation)
|
||||
// mapDataAlt.text = String.format(getString(R.string.map_altitude), mapData.altitude)
|
||||
// mapDataDst.text = String.format(getString(R.string.map_distance), mapData.range)
|
||||
// mapDataLat.text =
|
||||
// String.format(getString(R.string.map_latitude), mapData.osmPos.lat)
|
||||
// mapDataLon.text =
|
||||
// String.format(getString(R.string.map_longitude), mapData.osmPos.lon)
|
||||
// mapDataQth.text = String.format(getString(R.string.map_qth), mapData.qthLoc)
|
||||
// mapDataVel.text = String.format(getString(R.string.map_velocity), mapData.velocity)
|
||||
// if (mapData.eclipsed) {
|
||||
// mapDataVisibility.text = getString(R.string.map_eclipsed)
|
||||
// } else {
|
||||
// mapDataVisibility.text = getString(R.string.map_visible)
|
||||
// }
|
||||
// }
|
||||
// binding.mapView.invalidate()
|
||||
//}
|
||||
|
||||
@Composable
|
||||
private fun MapView(
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -237,9 +256,10 @@ private fun rememberMapViewWithLifecycle(isLightTheme: Boolean): MapView {
|
||||
setMultiTouchControls(true)
|
||||
setUseDataConnection(false)
|
||||
setTileSource(tileSource)
|
||||
minZoomLevel = getMinZoom(resources.displayMetrics.heightPixels) + 0.25
|
||||
maxZoomLevel = 8.0
|
||||
controller.setZoom(minZoomLevel + 1)
|
||||
minZoomLevel = getMinZoom(resources.displayMetrics.heightPixels)
|
||||
maxZoomLevel = 7.0
|
||||
controller.setCenter(GeoPoint(48.8575, 6.3514))
|
||||
controller.setZoom(minZoomLevel + 2)
|
||||
zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
|
||||
overlayManager.tilesOverlay.loadingBackgroundColor = Color.TRANSPARENT
|
||||
overlayManager.tilesOverlay.loadingLineColor = Color.TRANSPARENT
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
package com.rtbishop.look4sat.presentation.radar
|
||||
|
||||
import androidx.compose.animation.core.LinearEasing
|
||||
import androidx.compose.animation.core.RepeatMode
|
||||
import androidx.compose.animation.core.animateFloat
|
||||
import androidx.compose.animation.core.infiniteRepeatable
|
||||
import androidx.compose.animation.core.rememberInfiniteTransition
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.MarqueeSpacing
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.basicMarquee
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -23,6 +30,7 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
@@ -80,7 +88,7 @@ private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) {
|
||||
CardIcon(onClick = addToCalendar, iconId = R.drawable.ic_calendar)
|
||||
}
|
||||
NextPassRow(pass = uiState.currentPass ?: getDefaultPass())
|
||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.aspectRatio(1f)) {
|
||||
Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.aspectRatio(1f)) {
|
||||
uiState.orbitalPos?.let { position ->
|
||||
ElevatedCard {
|
||||
RadarViewCompose(
|
||||
@@ -127,6 +135,30 @@ private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) {
|
||||
)
|
||||
}
|
||||
}
|
||||
if (uiState.orbitalPos.eclipsed) {
|
||||
val infiniteTransition = rememberInfiniteTransition()
|
||||
val textAlpha = infiniteTransition.animateFloat(
|
||||
initialValue = 1.0f,
|
||||
targetValue = 0.0f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(
|
||||
durationMillis = 500,
|
||||
delayMillis = 25,
|
||||
easing = LinearEasing
|
||||
),
|
||||
repeatMode = RepeatMode.Reverse
|
||||
))
|
||||
Text(
|
||||
text = "Eclipsed!",
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier
|
||||
.alpha(textAlpha.value)
|
||||
.border(2.dp, MaterialTheme.colorScheme.primary, MaterialTheme.shapes.medium)
|
||||
.padding(16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
ElevatedCard(modifier = Modifier.fillMaxSize()) {
|
||||
|
||||
@@ -53,7 +53,7 @@ fun RadarViewCompose(
|
||||
val radarColor = MaterialTheme.colorScheme.secondary
|
||||
val trackColor = MaterialTheme.colorScheme.primary
|
||||
val aimColor = MaterialTheme.colorScheme.error
|
||||
val strokeWidth = 4f
|
||||
val strokeWidth = 6f
|
||||
val animTransition = rememberInfiniteTransition(label = "animScale")
|
||||
val animSpec = infiniteRepeatable<Float>(tween(1000))
|
||||
val animScale = animTransition.animateFloat(16f, 64f, animSpec, label = "animScale")
|
||||
@@ -167,7 +167,7 @@ private fun DrawScope.drawInfo(radius: Float, color: Color, measurer: TextMeasur
|
||||
}
|
||||
|
||||
private fun DrawScope.drawTrack(path: Path, effect: PathEffect, color: Color, effectColor: Color) {
|
||||
drawPath(path, color, style = Stroke(4f))
|
||||
drawPath(path, color, style = Stroke(6f))
|
||||
drawPath(path, effectColor, style = Stroke(pathEffect = effect))
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ private fun createTrackPath(positions: List<OrbitalPos>, radius: Float): Path {
|
||||
|
||||
private fun createTrackEffect(trackPath: Path): PathEffect {
|
||||
val shape = Path()
|
||||
val shapeRadius = 16f
|
||||
val shapeRadius = 24f
|
||||
val angle = 120.0.toRadians()
|
||||
shape.moveTo((shapeRadius * cos(angle)).toFloat(), (shapeRadius * sin(angle)).toFloat())
|
||||
for (i in 1 until 3) {
|
||||
|
||||
File renamed without changes.
File renamed without changes.
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
@@ -12,7 +12,7 @@ android {
|
||||
namespace = "com.rtbishop.look4sat.data"
|
||||
compileSdk = 35
|
||||
defaultConfig {
|
||||
minSdk = 26
|
||||
minSdk = 24
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[versions]
|
||||
android-gradle-plugin = "8.7.3"
|
||||
android-gradle-plugin = "8.8.0"
|
||||
google-ksp = "2.0.21-1.0.26"
|
||||
kotlin = "2.0.21"
|
||||
|
||||
@@ -7,18 +7,18 @@ androidx-core-ktx = "1.15.0"
|
||||
androidx-core-splashscreen = "1.0.1"
|
||||
androidx-room = "2.6.1"
|
||||
|
||||
compose-bom = "2024.11.00"
|
||||
compose-activity = "1.9.3"
|
||||
compose-bom = "2025.01.00"
|
||||
compose-activity = "1.10.0"
|
||||
compose-lifecycle = "2.8.7"
|
||||
compose-navigation = "2.8.4"
|
||||
compose-navigation = "2.8.5"
|
||||
|
||||
other-coroutines = "1.9.0"
|
||||
other-coroutines = "1.10.1"
|
||||
other-json = "20240303"
|
||||
other-okhttp = "4.12.0"
|
||||
other-osmdroid = "6.1.20"
|
||||
|
||||
test-junit4 = "4.13.2"
|
||||
test-mockk = "1.13.13"
|
||||
test-mockk = "1.13.14"
|
||||
|
||||
androidTest-junit = "1.2.1"
|
||||
androidTest-espresso = "3.6.1"
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
#Fri Oct 25 23:59:14 BST 2024
|
||||
#Sat Jan 04 21:11:19 GMT 2025
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
Reference in new issue
Block a user