mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-05 12:07:25 +00:00
Added several tweaks to TimerRow and NextPassRow
This commit is contained in:
1 parent
08767c5589
commit
68d814d996
15 files changed
+270
-133
No files matched your search
@@ -4,13 +4,15 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.basicMarquee
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
@@ -21,97 +23,158 @@ import androidx.compose.material3.CircularProgressIndicator
|
|||||||
import androidx.compose.material3.ElevatedButton
|
import androidx.compose.material3.ElevatedButton
|
||||||
import androidx.compose.material3.ElevatedCard
|
import androidx.compose.material3.ElevatedCard
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
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.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
import androidx.compose.ui.text.PlatformTextStyle
|
|
||||||
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.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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 com.rtbishop.look4sat.R
|
import com.rtbishop.look4sat.R
|
||||||
|
import com.rtbishop.look4sat.domain.predict.NearEarthObject
|
||||||
|
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.MainTheme
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
private val sdf = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
private fun TimerBarNewPreview() {
|
private fun TimerRowPreview() = MainTheme {
|
||||||
MainTheme { TimerBarNew("88:88:88", "88:88:88") }
|
TimerRow {
|
||||||
|
CardIcon(onClick = {}, iconId = R.drawable.ic_filter)
|
||||||
|
TimerBar(timeString = "88:88:88", isTimeAos = true)
|
||||||
|
CardIcon(onClick = {}, iconId = R.drawable.ic_satellite)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TimerBarNew(aosTime: String, losTime: String) {
|
fun TimerRow(content: @Composable (RowScope.() -> Unit)) {
|
||||||
val isAosSelected = remember { mutableStateOf(true) }
|
Row(
|
||||||
val barHeightMod = Modifier.height(48.dp)
|
modifier = Modifier.height(48.dp),
|
||||||
val timerText = if (isAosSelected.value) aosTime else losTime
|
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(6.dp)) {
|
verticalAlignment = Alignment.CenterVertically
|
||||||
CardAosLos(onClick = { isAosSelected.value = true }, iconId = R.drawable.ic_aos, isAosSelected.value)
|
) { content() }
|
||||||
ElevatedCard(modifier = barHeightMod.weight(1f)) {
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RowScope.TimerBar(timeString: String, isTimeAos: Boolean) {
|
||||||
|
val aosColor = if (isTimeAos) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface
|
||||||
|
val losColor = if (!isTimeAos) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface
|
||||||
|
ElevatedCard(modifier = Modifier.weight(1f)) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Text(text = "AOS", fontSize = 16.sp, color = aosColor)
|
||||||
Text(
|
Text(
|
||||||
text = "T- $timerText",
|
text = timeString,
|
||||||
textAlign = TextAlign.Center,
|
fontSize = 32.sp,
|
||||||
fontSize = 42.sp,
|
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = MaterialTheme.colorScheme.primary
|
||||||
style = TextStyle(platformStyle = PlatformTextStyle(includeFontPadding = false)),
|
|
||||||
modifier = Modifier.fillMaxSize()
|
|
||||||
)
|
)
|
||||||
|
Text(text = "LOS", fontSize = 16.sp, color = losColor)
|
||||||
}
|
}
|
||||||
CardAosLos(onClick = { isAosSelected.value = false }, iconId = R.drawable.ic_los, isAosSelected.value.not())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
private fun TimerBarPreview() {
|
private fun NextPassRowPreview() = MainTheme {
|
||||||
MainTheme { TimerBar(45555, "Satellite", "88:88:88", R.drawable.ic_filter) {} }
|
NextPassRow(pass = getDefaultPass())
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TimerBar(id: Int, name: String, time: String, iconId: Int, action: () -> Unit) {
|
fun NextPassRow(pass: OrbitalPass) {
|
||||||
val barHeightMod = Modifier.height(48.dp)
|
ElevatedCard {
|
||||||
val maxSizeMod = Modifier.fillMaxSize()
|
Column(
|
||||||
Row(
|
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
modifier = Modifier
|
||||||
horizontalArrangement = Arrangement.spacedBy(6.dp)
|
.background(color = MaterialTheme.colorScheme.surface)
|
||||||
) {
|
.padding(horizontal = 6.dp, vertical = 4.dp)
|
||||||
ElevatedCard(modifier = barHeightMod.weight(1f)) {
|
) {
|
||||||
Row(
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
modifier = maxSizeMod.padding(horizontal = 6.dp, vertical = 4.dp),
|
|
||||||
verticalAlignment = Alignment.Top
|
|
||||||
) {
|
|
||||||
Text(
|
Text(
|
||||||
text = "Id:$id - ",
|
text = "Id:${pass.catNum} - ",
|
||||||
modifier = Modifier.width(82.dp),
|
modifier = Modifier.width(82.dp),
|
||||||
textAlign = TextAlign.End,
|
textAlign = TextAlign.End,
|
||||||
color = MaterialTheme.colorScheme.primary
|
color = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = name,
|
text = pass.name,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(end = 6.dp),
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
modifier = Modifier.basicMarquee(iterations = Int.MAX_VALUE)
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.ic_elevation),
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.primary,
|
||||||
|
modifier = Modifier.size(16.dp)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = " ${pass.maxElevation}°",
|
||||||
|
textAlign = TextAlign.End,
|
||||||
|
color = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.pass_aosAz, pass.aosAzimuth),
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.pass_altitude, pass.altitude),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier.weight(2f)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.pass_losAz, pass.losAzimuth),
|
||||||
|
textAlign = TextAlign.End,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
val defaultTime = " - - : - - "
|
||||||
|
Text(text = if (pass.isDeepSpace) defaultTime else sdf.format(Date(pass.aosTime)), fontSize = 15.sp)
|
||||||
|
LinearProgressIndicator(
|
||||||
|
progress = { if (pass.isDeepSpace) 100f else pass.progress },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(0.75f)
|
||||||
|
.padding(top = 2.dp),
|
||||||
|
trackColor = MaterialTheme.colorScheme.inverseSurface
|
||||||
|
)
|
||||||
|
Text(text = if (pass.isDeepSpace) defaultTime else sdf.format(Date(pass.losTime)), fontSize = 15.sp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ElevatedCard(modifier = barHeightMod) {
|
|
||||||
Text(
|
|
||||||
text = time,
|
|
||||||
fontSize = 32.sp,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
color = MaterialTheme.colorScheme.primary,
|
|
||||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 6.dp),
|
|
||||||
style = TextStyle(platformStyle = PlatformTextStyle(includeFontPadding = false))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
CardIcon(onClick = { action() }, iconId = iconId)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,17 +199,17 @@ fun CardIcon(onClick: () -> Unit, iconId: Int, description: String? = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CardAosLos(onClick: () -> Unit, iconId: Int, isAos: Boolean = true, description: String? = null) {
|
fun StatusIcon(iconResId: Int, isEnabled: Boolean = false, description: String? = null, onClick: (() -> Unit)? = null) {
|
||||||
val cardColors = if (isAos) {
|
val cardColors = if (isEnabled) {
|
||||||
CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primary)
|
CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primary)
|
||||||
} else {
|
} else {
|
||||||
CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface)
|
CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface)
|
||||||
}
|
}
|
||||||
val iconTint = if (isAos) MaterialTheme.colorScheme.surface else MaterialTheme.colorScheme.onSurface
|
val clickableModifier = if (onClick != null) Modifier.clickable { onClick.invoke() } else Modifier
|
||||||
val clickableModifier = Modifier.clickable { onClick() }
|
val iconTint = if (isEnabled) MaterialTheme.colorScheme.surface else MaterialTheme.colorScheme.onSurface
|
||||||
ElevatedCard(modifier = Modifier.size(48.dp), colors = cardColors) {
|
ElevatedCard(modifier = Modifier.size(48.dp), colors = cardColors) {
|
||||||
Box(modifier = clickableModifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
Box(modifier = clickableModifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
Icon(imageVector = ImageVector.vectorResource(iconId), tint = iconTint, contentDescription = description)
|
Icon(imageVector = ImageVector.vectorResource(iconResId), tint = iconTint, contentDescription = description)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,6 +229,12 @@ fun gotoUrl(context: Context, url: String) {
|
|||||||
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 satellite = NearEarthObject(orbitalData)
|
||||||
|
return OrbitalPass(0L, 0.0, 0L, 0.0, 0, 0.0, satellite, 0f)
|
||||||
|
}
|
||||||
|
|
||||||
//fun Modifier.onClick(onClick: () -> Unit): Modifier = composed {
|
//fun Modifier.onClick(onClick: () -> Unit): Modifier = composed {
|
||||||
// clickable(remember { MutableInteractionSource() }, null) { onClick() }
|
// clickable(remember { MutableInteractionSource() }, null) { onClick() }
|
||||||
//}
|
//}
|
||||||
@@ -37,10 +37,12 @@ import com.rtbishop.look4sat.domain.predict.NearEarthObject
|
|||||||
import com.rtbishop.look4sat.domain.predict.OrbitalData
|
import com.rtbishop.look4sat.domain.predict.OrbitalData
|
||||||
import com.rtbishop.look4sat.domain.predict.OrbitalPass
|
import com.rtbishop.look4sat.domain.predict.OrbitalPass
|
||||||
import com.rtbishop.look4sat.presentation.MainTheme
|
import com.rtbishop.look4sat.presentation.MainTheme
|
||||||
|
import com.rtbishop.look4sat.presentation.components.CardIcon
|
||||||
|
import com.rtbishop.look4sat.presentation.components.NextPassRow
|
||||||
import com.rtbishop.look4sat.presentation.components.PullRefreshIndicator
|
import com.rtbishop.look4sat.presentation.components.PullRefreshIndicator
|
||||||
import com.rtbishop.look4sat.presentation.components.PullRefreshState
|
import com.rtbishop.look4sat.presentation.components.PullRefreshState
|
||||||
import com.rtbishop.look4sat.presentation.components.TimerBar
|
import com.rtbishop.look4sat.presentation.components.TimerBar
|
||||||
import com.rtbishop.look4sat.presentation.components.TimerBarNew
|
import com.rtbishop.look4sat.presentation.components.TimerRow
|
||||||
import com.rtbishop.look4sat.presentation.components.pullRefresh
|
import com.rtbishop.look4sat.presentation.components.pullRefresh
|
||||||
import com.rtbishop.look4sat.presentation.components.rememberPullRefreshState
|
import com.rtbishop.look4sat.presentation.components.rememberPullRefreshState
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
@@ -51,9 +53,8 @@ private val sdf = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PassesScreen(uiState: PassesState, navToRadar: (Int, Long) -> Unit) {
|
fun PassesScreen(uiState: PassesState, navToRadar: (Int, Long) -> Unit) {
|
||||||
val refreshState = rememberPullRefreshState(refreshing = uiState.isRefreshing, onRefresh = {
|
val refreshPasses = { uiState.takeAction(PassesAction.RefreshPasses) }
|
||||||
uiState.takeAction(PassesAction.RefreshPasses)
|
val refreshState = rememberPullRefreshState(refreshing = uiState.isRefreshing, onRefresh = refreshPasses)
|
||||||
})
|
|
||||||
val toggleDialog = { uiState.takeAction(PassesAction.ToggleFilterDialog) }
|
val toggleDialog = { uiState.takeAction(PassesAction.ToggleFilterDialog) }
|
||||||
if (uiState.isDialogShown) {
|
if (uiState.isDialogShown) {
|
||||||
FilterDialog(uiState.hours, uiState.elevation, uiState.modes, toggleDialog) { hours, elevation, modes ->
|
FilterDialog(uiState.hours, uiState.elevation, uiState.modes, toggleDialog) { hours, elevation, modes ->
|
||||||
@@ -61,17 +62,38 @@ fun PassesScreen(uiState: PassesState, navToRadar: (Int, Long) -> Unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||||
TimerBarNew(aosTime = uiState.nextTime, losTime = uiState.nextTime)
|
TimerRow {
|
||||||
TimerBar(
|
CardIcon(onClick = { toggleDialog() }, iconId = R.drawable.ic_filter)
|
||||||
id = uiState.nextId,
|
TimerBar(timeString = uiState.nextTime, isTimeAos = uiState.isNextTimeAos)
|
||||||
name = uiState.nextName,
|
CardIcon(onClick = { toggleDialog() }, iconId = R.drawable.ic_satellite)
|
||||||
time = uiState.nextTime,
|
}
|
||||||
iconId = R.drawable.ic_filter
|
NextPassRow(pass = uiState.nextPass)
|
||||||
) { toggleDialog() }
|
PassesList(refreshState, uiState.isRefreshing, uiState.itemsList, navToRadar)
|
||||||
PassesCard(refreshState, uiState.isRefreshing, uiState.itemsList, navToRadar)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
private fun PassesList(
|
||||||
|
refreshState: PullRefreshState,
|
||||||
|
isRefreshing: Boolean,
|
||||||
|
passes: List<OrbitalPass>,
|
||||||
|
navToRadar: (Int, Long) -> Unit
|
||||||
|
) {
|
||||||
|
val backgroundColor = MaterialTheme.colorScheme.primary
|
||||||
|
ElevatedCard(modifier = Modifier.fillMaxSize()) {
|
||||||
|
Box(Modifier.pullRefresh(refreshState), contentAlignment = Alignment.TopCenter) {
|
||||||
|
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||||
|
items(items = passes, key = { item -> item.catNum + item.aosTime }) { pass ->
|
||||||
|
PassItem(pass = pass, navToRadar = navToRadar, modifier = Modifier.animateItemPlacement())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PullRefreshIndicator(refreshing = isRefreshing, state = refreshState, backgroundColor = backgroundColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
private fun DeepSpacePassPreview() {
|
private fun DeepSpacePassPreview() {
|
||||||
@@ -80,7 +102,7 @@ private fun DeepSpacePassPreview() {
|
|||||||
)
|
)
|
||||||
val satellite = DeepSpaceObject(data)
|
val satellite = DeepSpaceObject(data)
|
||||||
val pass = OrbitalPass(1L, 0.0, 10L, 180.0, 850, 45.0, satellite, 0.5f)
|
val pass = OrbitalPass(1L, 0.0, 10L, 180.0, 850, 45.0, satellite, 0.5f)
|
||||||
MainTheme { Pass(pass = pass, { _, _ -> }) }
|
MainTheme { PassItem(pass = pass, { _, _ -> }) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
@@ -91,13 +113,11 @@ private fun NearEarthPassPreview() {
|
|||||||
)
|
)
|
||||||
val satellite = NearEarthObject(data)
|
val satellite = NearEarthObject(data)
|
||||||
val pass = OrbitalPass(1L, 0.0, 10L, 180.0, 850, 45.0, satellite, 0.5f)
|
val pass = OrbitalPass(1L, 0.0, 10L, 180.0, 850, 45.0, satellite, 0.5f)
|
||||||
MainTheme { Pass(pass = pass, { _, _ -> }) }
|
MainTheme { PassItem(pass = pass, { _, _ -> }) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun Pass(
|
private fun PassItem(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifier: Modifier = Modifier) {
|
||||||
pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifier: Modifier = Modifier
|
|
||||||
) {
|
|
||||||
Surface(color = MaterialTheme.colorScheme.background, modifier = modifier) {
|
Surface(color = MaterialTheme.colorScheme.background, modifier = modifier) {
|
||||||
Surface(modifier = Modifier
|
Surface(modifier = Modifier
|
||||||
.padding(bottom = 2.dp)
|
.padding(bottom = 2.dp)
|
||||||
@@ -105,8 +125,8 @@ private fun Pass(
|
|||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(MaterialTheme.colorScheme.surface)
|
.background(color = MaterialTheme.colorScheme.surface)
|
||||||
.padding(6.dp)
|
.padding(horizontal = 6.dp, vertical = 4.dp)
|
||||||
) {
|
) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Text(
|
Text(
|
||||||
@@ -160,55 +180,23 @@ private fun Pass(
|
|||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (!pass.isDeepSpace) {
|
Row(
|
||||||
Row(
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
modifier = Modifier.fillMaxWidth()
|
||||||
modifier = Modifier.fillMaxWidth()
|
) {
|
||||||
) {
|
val defaultTime = " - - : - - "
|
||||||
Text(
|
Text(text = if (pass.isDeepSpace) defaultTime else sdf.format(Date(pass.aosTime)), fontSize = 15.sp)
|
||||||
text = sdf.format(Date(pass.aosTime)),
|
LinearProgressIndicator(
|
||||||
fontSize = 15.sp
|
progress = { if (pass.isDeepSpace) 100f else pass.progress },
|
||||||
)
|
modifier = modifier
|
||||||
LinearProgressIndicator(
|
.fillMaxWidth(0.75f)
|
||||||
progress = pass.progress,
|
.padding(top = 2.dp),
|
||||||
modifier = modifier
|
trackColor = MaterialTheme.colorScheme.inverseSurface
|
||||||
.fillMaxWidth(0.75f)
|
)
|
||||||
.padding(top = 3.dp),
|
Text(text = if (pass.isDeepSpace) defaultTime else sdf.format(Date(pass.losTime)), fontSize = 15.sp)
|
||||||
trackColor = MaterialTheme.colorScheme.inverseSurface
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = sdf.format(Date(pass.losTime)),
|
|
||||||
fontSize = 15.sp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
private fun PassesCard(
|
|
||||||
refreshState: PullRefreshState,
|
|
||||||
isRefreshing: Boolean,
|
|
||||||
passes: List<OrbitalPass>,
|
|
||||||
navToRadar: (Int, Long) -> Unit
|
|
||||||
) {
|
|
||||||
ElevatedCard(modifier = Modifier.fillMaxSize()) {
|
|
||||||
Box(Modifier.pullRefresh(refreshState)) {
|
|
||||||
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
|
||||||
items(items = passes, key = { item -> item.catNum + item.aosTime }) { pass ->
|
|
||||||
Pass(pass, navToRadar, Modifier.animateItemPlacement())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PullRefreshIndicator(
|
|
||||||
refreshing = isRefreshing,
|
|
||||||
state = refreshState,
|
|
||||||
modifier = Modifier.align(Alignment.TopCenter),
|
|
||||||
backgroundColor = MaterialTheme.colorScheme.primary
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,9 +6,9 @@ data class PassesState(
|
|||||||
val isDialogShown: Boolean,
|
val isDialogShown: Boolean,
|
||||||
val isRefreshing: Boolean,
|
val isRefreshing: Boolean,
|
||||||
val isUtc: Boolean,
|
val isUtc: Boolean,
|
||||||
val nextId: Int,
|
val nextPass: OrbitalPass,
|
||||||
val nextName: String,
|
|
||||||
val nextTime: String,
|
val nextTime: String,
|
||||||
|
val isNextTimeAos: Boolean,
|
||||||
val hours: Int,
|
val hours: Int,
|
||||||
val elevation: Double,
|
val elevation: Double,
|
||||||
val modes: List<String>,
|
val modes: List<String>,
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import com.rtbishop.look4sat.domain.predict.OrbitalPass
|
|||||||
import com.rtbishop.look4sat.domain.repository.ISatelliteRepo
|
import com.rtbishop.look4sat.domain.repository.ISatelliteRepo
|
||||||
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
||||||
import com.rtbishop.look4sat.domain.utility.toTimerString
|
import com.rtbishop.look4sat.domain.utility.toTimerString
|
||||||
|
import com.rtbishop.look4sat.presentation.components.getDefaultPass
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.cancelAndJoin
|
import kotlinx.coroutines.cancelAndJoin
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@@ -45,9 +46,9 @@ class PassesViewModel(
|
|||||||
isDialogShown = false,
|
isDialogShown = false,
|
||||||
isRefreshing = true,
|
isRefreshing = true,
|
||||||
isUtc = settingsRepo.otherSettings.value.stateOfUtc,
|
isUtc = settingsRepo.otherSettings.value.stateOfUtc,
|
||||||
nextId = 0,
|
|
||||||
nextName = "...",
|
|
||||||
nextTime = "00:00:00",
|
nextTime = "00:00:00",
|
||||||
|
isNextTimeAos = true,
|
||||||
|
nextPass = getDefaultPass(),
|
||||||
hours = settingsRepo.passesSettings.value.hoursAhead,
|
hours = settingsRepo.passesSettings.value.hoursAhead,
|
||||||
elevation = settingsRepo.passesSettings.value.minElevation,
|
elevation = settingsRepo.passesSettings.value.minElevation,
|
||||||
modes = settingsRepo.passesSettings.value.selectedModes,
|
modes = settingsRepo.passesSettings.value.selectedModes,
|
||||||
@@ -103,11 +104,11 @@ class PassesViewModel(
|
|||||||
try {
|
try {
|
||||||
val nextPass = passes.first { it.aosTime.minus(timeNow) > 0 }
|
val nextPass = passes.first { it.aosTime.minus(timeNow) > 0 }
|
||||||
val time = nextPass.aosTime.minus(timeNow).toTimerString()
|
val time = nextPass.aosTime.minus(timeNow).toTimerString()
|
||||||
_uiState.value = _uiState.value.copy(nextId = nextPass.catNum, nextName = nextPass.name, nextTime = time)
|
_uiState.value = _uiState.value.copy(nextPass = nextPass, nextTime = time, isNextTimeAos = true)
|
||||||
} catch (exception: NoSuchElementException) {
|
} catch (exception: NoSuchElementException) {
|
||||||
val lastPass = passes.last()
|
val lastPass = passes.last()
|
||||||
val time = lastPass.losTime.minus(timeNow).toTimerString()
|
val time = lastPass.losTime.minus(timeNow).toTimerString()
|
||||||
_uiState.value = _uiState.value.copy(nextId = lastPass.catNum, nextName = lastPass.name, nextTime = time)
|
_uiState.value = _uiState.value.copy(nextPass = lastPass, nextTime = time, isNextTimeAos = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ 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.domain.model.SatRadio
|
import com.rtbishop.look4sat.domain.model.SatRadio
|
||||||
import com.rtbishop.look4sat.presentation.components.TimerBar
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RadarScreen() {
|
fun RadarScreen() {
|
||||||
@@ -36,7 +35,7 @@ fun RadarScreen() {
|
|||||||
val id = currentPass?.catNum ?: 99999
|
val id = currentPass?.catNum ?: 99999
|
||||||
val name = currentPass?.name ?: "Satellite"
|
val name = currentPass?.name ?: "Satellite"
|
||||||
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||||
TimerBar(id, name, "88:88:88", R.drawable.ic_notifications) {}
|
// TimerBarNew(id, name, "88:88:88", R.drawable.ic_notifications) {}
|
||||||
ElevatedCard(
|
ElevatedCard(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
|||||||
@@ -5,5 +5,5 @@
|
|||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M9,5v2h6.59L4,18.59L5.41,20L17,8.41V15h2V5H9z" />
|
android:pathData="M4,20h16v2L4,22zM4,2h16v2L4,4zM13,9h3l-4,-4 -4,4h3v6L8,15l4,4 4,-4h-3z" />
|
||||||
</vector>
|
</vector>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M17.06,11.57C17.65,10.88 18,9.98 18,9c0,-1.86 -1.27,-3.43 -3,-3.87L15,3h-2v2h-2V3H9v2H6v2h2v10H6v2h3v2h2v-2h2v2h2v-2c2.21,0 4,-1.79 4,-4C19,13.55 18.22,12.27 17.06,11.57zM10,7h4c1.1,0 2,0.9 2,2s-0.9,2 -2,2h-4V7zM15,17h-5v-4h5c1.1,0 2,0.9 2,2S16.1,17 15,17z" />
|
||||||
|
</vector>
|
||||||
+1
-1
@@ -5,5 +5,5 @@
|
|||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M16,18H6V8h3v4.77L15.98,6 18,8.03 11.15,15H16v3z" />
|
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z" />
|
||||||
</vector>
|
</vector>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8.46,11.88l1.41,-1.41L12,12.59l2.12,-2.12 1.41,1.41L13.41,14l2.12,2.12 -1.41,1.41L12,15.41l-2.12,2.12 -1.41,-1.41L10.59,14l-2.13,-2.12zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M11.8,10.9c-2.27,-0.59 -3,-1.2 -3,-2.15 0,-1.09 1.01,-1.85 2.7,-1.85 1.78,0 2.44,0.85 2.5,2.1h2.21c-0.07,-1.72 -1.12,-3.3 -3.21,-3.81V3h-3v2.16c-1.94,0.42 -3.5,1.68 -3.5,3.61 0,2.31 1.91,3.46 4.7,4.13 2.5,0.6 3,1.48 3,2.41 0,0.69 -0.49,1.79 -2.7,1.79 -2.06,0 -2.87,-0.92 -2.98,-2.1h-2.2c0.12,2.19 1.76,3.42 3.68,3.83V21h3v-2.15c1.95,-0.37 3.5,-1.5 3.5,-3.55 0,-2.84 -2.43,-3.81 -4.7,-4.4z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,8l-8,5 -8,-5L4,6l8,5 8,-5v2z" />
|
||||||
|
</vector>
|
||||||
@@ -5,5 +5,5 @@
|
|||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M19,9h-2v6.59L5.41,4L4,5.41L15.59,17H9v2h10V9z" />
|
android:pathData="M12.34,2.02C6.59,1.82 2,6.42 2,12c0,5.52 4.48,10 10,10c3.71,0 6.93,-2.02 8.66,-5.02C13.15,16.73 8.57,8.55 12.34,2.02z" />
|
||||||
</vector>
|
</vector>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M14,21c1.93,0 3.62,-1.17 4,-3l-1.75,-0.88C16,18.21 15.33,19 14,19l-4.9,0c0.83,-1 1.5,-2.34 1.5,-4c0,-0.35 -0.03,-0.69 -0.08,-1L14,14v-2l-4.18,0C9,10.42 8,9.6 8,8c0,-1.93 1.57,-3.5 3.5,-3.5c1.5,0 2.79,0.95 3.28,2.28L16.63,6c-0.8,-2.05 -2.79,-3.5 -5.13,-3.5C8.46,2.5 6,4.96 6,8c0,1.78 0.79,2.9 1.49,4L6,12v2l2.47,0c0.08,0.31 0.13,0.64 0.13,1c0,2.7 -2.6,4 -2.6,4v2H14z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="128"
|
||||||
|
android:viewportHeight="128">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="m105.14,114.12a2.86,2.86 90,0 0,1.7 -0.85l19.33,-19.33a2.86,2.86 90,0 0,-0 -4.03l-26.58,-26.62a2.86,2.86 90,0 0,-1.84 -0.81l-7.92,-0.63 5.77,-5.77a2.86,2.86 90,0 0,-0 -4.03l-19.6,-19.64a2.86,2.86 90,0 0,-4.07 -0l-5.77,5.77 -0.63,-7.92a2.86,2.86 90,0 0,-0.81 -1.83l-26.63,-26.58a2.86,2.86 90,0 0,-4.07 -0l-19.29,19.29a2.86,2.86 90,0 0,-0 4.07l26.58,26.62a2.86,2.86 90,0 0,1.83 0.81l7.92,0.63 -5.77,5.77a2.86,2.86 90,0 0,-0 4.07l19.6,19.6a2.86,2.86 90,0 0,4.07 -0l5.77,-5.77 0.63,7.92a2.86,2.86 90,0 0,0.81 1.83l26.63,26.58a2.86,2.86 90,0 0,2.06 0.85,2.86 2.86,90 0,0 0.27,-0zM104.82,107.23 L80.97,83.38 80.16,72.69 85.58,67.27 96.28,68.12 120.13,91.93zM55.33,47.85 L44.63,47 20.78,23.19 36.08,7.89 59.89,31.74 60.74,42.44z"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="m62.65,115.81a2.86,2.86 90,1 0,-0 -5.73c-11.46,-0 -22.88,-4.35 -31.63,-13.11 -8.74,-8.74 -13.1,-20.17 -13.1,-31.61a2.86,2.86 90,1 0,-5.73 -0c-0,12.9 4.94,25.83 14.77,35.66 9.85,9.85 22.77,14.78 35.68,14.78z"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="m62.65,127a2.86,2.86 90,1 0,-0 -5.73c-14.32,-0 -28.61,-5.44 -39.55,-16.37 -10.93,-10.93 -16.38,-25.23 -16.38,-39.54a2.86,2.86 90,1 0,-5.73 -0c-0,15.76 6.03,31.56 18.06,43.59 12.03,12.03 27.82,18.05 43.6,18.05z"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="m62.65,104.7a2.86,2.86 90,1 0,-0 -5.73c-8.62,-0 -17.2,-3.26 -23.78,-9.84 -6.58,-6.58 -9.86,-15.17 -9.86,-23.77a2.86,2.86 90,1 0,-5.73 -0c-0,10.06 3.86,20.15 11.53,27.82 7.67,7.67 17.76,11.52 27.83,11.52z"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="m62.65,93.48a2.86,2.86 90,1 0,-0 -5.73c-5.74,-0 -11.45,-2.17 -15.84,-6.56 -4.38,-4.38 -6.56,-10.1 -6.56,-15.83a2.86,2.86 90,1 0,-5.73 -0c-0,7.19 2.76,14.41 8.24,19.88 5.48,5.48 12.69,8.23 19.89,8.23z"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M6.76,4.84l-1.8,-1.79 -1.41,1.41 1.79,1.79 1.42,-1.41zM4,10.5L1,10.5v2h3v-2zM13,0.55h-2L11,3.5h2L13,0.55zM20.45,4.46l-1.41,-1.41 -1.79,1.79 1.41,1.41 1.79,-1.79zM17.24,18.16l1.79,1.8 1.41,-1.41 -1.8,-1.79 -1.4,1.4zM20,10.5v2h3v-2h-3zM12,5.5c-3.31,0 -6,2.69 -6,6s2.69,6 6,6 6,-2.69 6,-6 -2.69,-6 -6,-6zM11,22.45h2L13,19.5h-2v2.95zM3.55,18.54l1.41,1.41 1.79,-1.8 -1.41,-1.41 -1.79,1.8z" />
|
||||||
|
</vector>
|
||||||
Reference in new issue
Block a user